Library support and several libraries added. Hot reload added.

This commit is contained in:
Scott Duensing 2026-07-02 21:51:13 -05:00
parent 6c644064dd
commit 0a82eb2ac9
13659 changed files with 6753238 additions and 16 deletions

126
Makefile
View file

@ -27,8 +27,8 @@ LDFLAGS = $(SAN)
# Our headers: src/ plus the per-language subdirs. VPATH lets the object rules find
# a source by name without spelling out its directory.
INC = -Isrc -Isrc/lua -Isrc/mybasic -Isrc/squirrel -Isrc/js -Isrc/berry -Isrc/s7 -Isrc/wren
VPATH = src:src/lua:src/mybasic:src/squirrel:src/js:src/berry:src/s7:src/wren:tests
INC = -Isrc -Isrc/lua -Isrc/mybasic -Isrc/squirrel -Isrc/js -Isrc/berry -Isrc/s7 -Isrc/wren -Ilibs
VPATH = src:src/lua:src/mybasic:src/squirrel:src/js:src/berry:src/s7:src/wren:libs:tests
CORE = obj/value.o obj/broker.o
@ -119,9 +119,24 @@ WRENFLAGS = -std=c99 -w -g -O1
WRENOBJ = obj/wren.o
WRENLIBS = -lm
# --- vendored SQLite (C amalgamation, single file). THREADSAFE=1 (serialized) because
# the DB natives run inline on many context threads. Links -lm -lpthread. ---
SQLITEDIR = vendor/sqlite
SQLITEINC = -I$(SQLITEDIR)
SQLITEFLAGS = -std=c11 -w -g -O2 -DSQLITE_THREADSAFE=1 -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_OMIT_LOAD_EXTENSION
SQLITEOBJ = obj/sqlite3.o
SQLITELIBS = -lm -lpthread
# --- vendored ENet (reliable UDP; all sources except win32.c) for calogNet's ENet backend.
ENETDIR = vendor/enet
ENETINC = -I$(ENETDIR)/include
ENETFLAGS = -std=c11 -w -g -O2 -D_GNU_SOURCE -DHAS_FCNTL=1 -DHAS_POLL=1 -DHAS_GETADDRINFO=1 -DHAS_GETNAMEINFO=1 -DHAS_GETHOSTBYNAME_R=1 -DHAS_GETHOSTBYADDR_R=1 -DHAS_INET_PTON=1 -DHAS_INET_NTOP=1 -DHAS_MSGHDR_FLAGS=1 -DHAS_SOCKLEN_T=1
ENETNAMES = callbacks compress host list packet peer protocol unix
ENETOBJ = $(foreach n,$(ENETNAMES),obj/enet_$(n).o)
BINS = bin/testBroker bin/testLua bin/testMyBasic bin/testPolyglot bin/testActor \
bin/testEngineLua bin/testEngineMyBasic bin/testSquirrel bin/testEngineSquirrel bin/testJs bin/testEngineJs \
bin/testEngineBerry bin/testEngineS7 bin/testEngineWren bin/testLoad bin/embed
bin/testEngineBerry bin/testEngineS7 bin/testEngineWren bin/testLoad bin/testDb bin/testNet bin/testTask bin/testExport bin/embed
all: $(BINS)
@ -133,7 +148,7 @@ $(STRICTOBJ): obj/%.o: %.c | obj
$(CC) $(COREFLAGS) $(INC) -c -o $@ $<
# strict C, threaded
THREADOBJ = obj/context.o obj/mybasicEngine.o obj/testActor.o obj/testEngineLua.o obj/testEngineSquirrel.o obj/testEngineJs.o obj/testEngineMyBasic.o obj/testEngineBerry.o obj/testEngineS7.o obj/testEngineWren.o
THREADOBJ = obj/context.o obj/mybasicEngine.o obj/testActor.o obj/testEngineLua.o obj/testEngineSquirrel.o obj/testEngineJs.o obj/testEngineMyBasic.o obj/testEngineBerry.o obj/testEngineS7.o obj/testEngineWren.o obj/calogHandle.o obj/testDb.o obj/testNet.o obj/testTask.o obj/calogExport.o obj/testExport.o
$(THREADOBJ): obj/%.o: %.c | obj
$(CC) $(COREFLAGS) $(INC) -pthread -c -o $@ $<
@ -172,6 +187,24 @@ WRENADP = obj/wrenAdapter.o
$(WRENADP): obj/%.o: %.c | obj
$(CC) $(ADPFLAGS) $(INC) $(WRENINC) -c -o $@ $<
# DB library adapter: relaxed C + SQLite headers, sqlite backend compiled in
DBADP = obj/calogDb.o
$(DBADP): obj/%.o: %.c | obj
$(CC) $(ADPFLAGS) $(INC) $(SQLITEINC) -DCALOG_WITH_SQLITE -c -o $@ $<
# network library: strict C + ENet headers, ENet backend compiled in (self-contained, so
# always enabled -- unlike the DB clients, ENet needs no server)
NETADP = obj/calogNet.o
$(NETADP): obj/%.o: %.c | obj
$(CC) $(COREFLAGS) $(INC) $(ENETINC) -DCALOG_WITH_ENET -pthread -c -o $@ $<
# task library: strict C with every engine name compiled in (it references each engine
# vtable under its CALOG_WITH_* guard), so a task-using binary links all engine archives.
ENGINEDEFS = -DCALOG_WITH_LUA -DCALOG_WITH_JS -DCALOG_WITH_SQUIRREL -DCALOG_WITH_MYBASIC -DCALOG_WITH_BERRY -DCALOG_WITH_S7 -DCALOG_WITH_WREN
TASKADP = obj/calogTask.o
$(TASKADP): obj/%.o: %.c | obj
$(CC) $(COREFLAGS) $(INC) $(ENGINEDEFS) -pthread -c -o $@ $<
# polyglot test pulls in both Lua and my-basic
obj/testPolyglot.o: testPolyglot.c | obj
$(CC) $(ADPFLAGS) $(INC) $(LUAINC) $(MBINC) -DMB_DOUBLE_FLOAT -c -o $@ $<
@ -201,6 +234,12 @@ obj/s7.o: $(S7DIR)/s7.c | obj
obj/wren.o: $(WRENDIR)/wren.c | obj
$(CC) $(WRENFLAGS) $(WRENINC) -c -o $@ $<
obj/sqlite3.o: $(SQLITEDIR)/sqlite3.c | obj
$(CC) $(SQLITEFLAGS) $(SQLITEINC) -c -o $@ $<
obj/enet_%.o: $(ENETDIR)/%.c | obj
$(CC) $(ENETFLAGS) $(ENETINC) -c -o $@ $<
# ---- library archives ----
# libcalog.a is calog itself (core + actor + every engine adapter/binding). The
# vendored engines are separate archives; a host links libcalog.a plus whichever
@ -227,6 +266,10 @@ lib/libs7.a: $(S7OBJ) | lib
ar rcs $@ $^
lib/libwren.a: $(WRENOBJ) | lib
ar rcs $@ $^
lib/libsqlite3.a: $(SQLITEOBJ) | lib
ar rcs $@ $^
lib/libenet.a: $(ENETOBJ) | lib
ar rcs $@ $^
# ---- binaries (link libcalog.a + the vendored engine archives they use) ----
bin/testBroker: obj/testBroker.o lib/libcalog.a | bin
@ -241,6 +284,41 @@ bin/testLua: obj/testLua.o lib/libcalog.a lib/liblua.a | bin
bin/testEngineLua: obj/testEngineLua.o lib/libcalog.a lib/liblua.a | bin
$(CC) $(LDFLAGS) -pthread -o $@ $^ $(LUALIBS)
# DB library test: calog + the DB library + vendored SQLite, driven from Lua.
bin/testDb: obj/testDb.o obj/calogDb.o obj/calogHandle.o lib/libcalog.a lib/liblua.a lib/libsqlite3.a | bin
$(CC) $(LDFLAGS) -pthread -o $@ $^ $(LUALIBS) $(SQLITELIBS)
# network library test: calog + the network library + vendored ENet, driven from Lua
# (TCP/UDP/ENet loopback).
bin/testNet: obj/testNet.o $(NETADP) obj/calogHandle.o lib/libcalog.a lib/liblua.a lib/libenet.a | bin
$(CC) $(LDFLAGS) -pthread -o $@ $^ $(LUALIBS)
# --- optional Postgres + MySQL DB-client tests. They pull in the vendored client archives
# + OpenSSL (PG archives need a link group), and their live round-trips need a running
# server, so they are opt-in and NOT part of `make test`. Build both with `make db-clients`,
# then run each with a connection string (see tests/testDbPg.c and tests/testDbMysql.c). ---
PGINC = -Ivendor/postgres/src/interfaces/libpq -Ivendor/postgres/src/include
PGARCHIVES = vendor/postgres/src/interfaces/libpq/libpq.a vendor/postgres/src/common/libpgcommon_shlib.a vendor/postgres/src/port/libpgport_shlib.a
MYSQLINC = -Ivendor/mariadb/include -Ivendor/mariadb/build/include
MYSQLARCH = vendor/mariadb/build/libmariadb/libmariadbclient.a
SSLARCH = vendor/openssl/libssl.a vendor/openssl/libcrypto.a
DBCLIENTOBJ = obj/testDbPg.o obj/testDbMysql.o
obj/calogDbFull.o: libs/calogDb.c | obj
$(CC) $(ADPFLAGS) $(INC) $(SQLITEINC) $(PGINC) $(MYSQLINC) -DCALOG_WITH_SQLITE -DCALOG_WITH_PG -DCALOG_WITH_MYSQL -c -o $@ $<
$(DBCLIENTOBJ): obj/%.o: %.c | obj
$(CC) $(COREFLAGS) $(INC) -pthread -c -o $@ $<
bin/testDbPg: obj/testDbPg.o obj/calogDbFull.o obj/calogHandle.o lib/libcalog.a lib/liblua.a lib/libsqlite3.a | bin
$(CC) $(LDFLAGS) -pthread -o $@ $^ -Wl,--start-group $(PGARCHIVES) -Wl,--end-group $(MYSQLARCH) $(SSLARCH) $(LUALIBS) $(SQLITELIBS)
bin/testDbMysql: obj/testDbMysql.o obj/calogDbFull.o obj/calogHandle.o lib/libcalog.a lib/liblua.a lib/libsqlite3.a | bin
$(CC) $(LDFLAGS) -pthread -o $@ $^ -Wl,--start-group $(PGARCHIVES) -Wl,--end-group $(MYSQLARCH) $(SSLARCH) $(LUALIBS) $(SQLITELIBS)
.PHONY: db-clients
db-clients: bin/testDbPg bin/testDbMysql
bin/testMyBasic: obj/testMyBasic.o lib/libcalog.a lib/libmybasic.a | bin
$(CC) $(LDFLAGS) -o $@ $^ -lm
@ -278,6 +356,35 @@ obj/embed.o: examples/embed.c src/calog.h | obj
bin/embed: obj/embed.o lib/libcalog.a lib/libquickjs.a | bin
$(CC) $(LDFLAGS) -pthread -o $@ $^ -lm
# ---- fully-static build --------------------------------------------------------------
# A self-contained calog executable with NO shared-library dependencies at runtime. The
# calog objects are recompiled without sanitizers (ASan does not support -static) into
# obj/rel/; the vendored archives (lua/sqlite/enet) are already un-sanitized and reused.
# The example embeds Lua + the SQLite DB library + the network library. Build + run with
# `make static`. (Static glibc cannot resolve names or dlopen C modules -- see
# examples/staticDemo.c; the dlopen/getaddrinfo link warnings are expected and harmless
# for a binary that uses neither.)
RELFLAGS = -std=c11 $(WARN) $(DEP) -O2
RELOBJ = obj/rel/value.o obj/rel/broker.o obj/rel/context.o obj/rel/luaEngine.o obj/rel/luaAdapter.o obj/rel/calogHandle.o obj/rel/calogDb.o obj/rel/calogNet.o
obj/rel:
mkdir -p obj/rel
$(RELOBJ): obj/rel/%.o: %.c | obj/rel
$(CC) $(RELFLAGS) $(INC) $(LUAINC) $(SQLITEINC) $(ENETINC) -DCALOG_WITH_SQLITE -DCALOG_WITH_ENET -pthread -c -o $@ $<
obj/rel/staticDemo.o: examples/staticDemo.c src/calog.h libs/calogDb.h libs/calogNet.h | obj/rel
$(CC) $(RELFLAGS) $(INC) -pthread -c -o $@ $<
bin/calogStatic: obj/rel/staticDemo.o $(RELOBJ) lib/liblua.a lib/libsqlite3.a lib/libenet.a | bin
$(CC) -static -pthread -o $@ $^ $(LUALIBS) $(SQLITELIBS)
.PHONY: static
static: bin/calogStatic
@file bin/calogStatic | grep -q "statically linked" && echo "== bin/calogStatic is fully static ==" || { echo "== NOT statically linked! =="; exit 1; }
@echo "runtime shared-lib deps:"; ldd bin/calogStatic 2>&1 | sed 's/^/ /'
./bin/calogStatic
# load test: links every engine (compiled with all CALOG_WITH_* engine flags) so it
# exercises calogContextLoad + calogRegisterBuiltinEngines across all four languages --
# including my-basic under the actor model. Uses only calog.h (the extern engine vtables).
@ -287,13 +394,21 @@ obj/testLoad.o: tests/testLoad.c src/calog.h | obj
bin/testLoad: obj/testLoad.o lib/libcalog.a lib/liblua.a lib/libquickjs.a lib/libsquirrel.a lib/libmybasic.a lib/libberry.a lib/libs7.a lib/libwren.a | bin
$(CC) $(LDFLAGS) -pthread -o $@ $^ $(LUALIBS) -lstdc++ -lm
# task library test: the task lib names every engine, so (like testLoad) it links them all.
bin/testTask: obj/testTask.o $(TASKADP) obj/calogHandle.o lib/libcalog.a lib/liblua.a lib/libquickjs.a lib/libsquirrel.a lib/libmybasic.a lib/libberry.a lib/libs7.a lib/libwren.a | bin
$(CC) $(LDFLAGS) -pthread -o $@ $^ $(LUALIBS) -lstdc++ -lm
# export library test: publish from Lua, call by bare name from Lua + via callExport from JS.
bin/testExport: obj/testExport.o obj/calogExport.o lib/libcalog.a lib/liblua.a lib/libquickjs.a lib/libsquirrel.a lib/libs7.a | bin
$(CC) $(LDFLAGS) -pthread -o $@ $^ $(LUALIBS) -lstdc++ -ldl -lm
obj bin lib:
mkdir -p $@
test: all
./bin/testBroker && ./bin/testLua && ./bin/testMyBasic && ./bin/testPolyglot && \
./bin/testActor && ./bin/testEngineLua && ./bin/testEngineMyBasic && ./bin/testSquirrel && ./bin/testEngineSquirrel && \
./bin/testJs && ./bin/testEngineJs && ./bin/testEngineBerry && ./bin/testEngineS7 && ./bin/testEngineWren && ./bin/testLoad
./bin/testJs && ./bin/testEngineJs && ./bin/testEngineBerry && ./bin/testEngineS7 && ./bin/testEngineWren && ./bin/testLoad && ./bin/testDb && ./bin/testNet && ./bin/testTask && ./bin/testExport
# ThreadSanitizer build of the actor core and the Lua engine path (cannot combine
# with ASan). Recompiled from source under TSan; the vendored Lua objects are
@ -377,5 +492,6 @@ clean:
rm -rf obj bin lib
-include $(wildcard obj/*.d)
-include $(wildcard obj/rel/*.d)
.PHONY: all test tsan tsansq tsanjs tsanmb tsanberry tsans7 tsanwren clean

112
examples/staticDemo.c Normal file
View file

@ -0,0 +1,112 @@
// staticDemo.c -- a self-contained calog application, built as a fully static binary.
//
// It embeds the Lua engine, the DB library (SQLite backend), and the network library, then
// runs one script that sums 1..10 through an in-memory database and opens/closes a UDP
// socket -- proving the engine, DB, and network stacks all work in a `-static` executable
// with no shared-library dependencies at runtime. Build it with `make static`.
//
// Static-glibc caveat: name resolution (getaddrinfo) and dlopen-based Lua C modules do not
// work in a fully static glibc binary -- connect by IP and avoid `require` of C modules, or
// link musl. This demo uses neither, so it is fully self-contained.
#define _POSIX_C_SOURCE 200809L
#include "calog.h"
#include "calogDb.h"
#include "calogNet.h"
#include <stdatomic.h>
#include <stdio.h>
#include <time.h>
static _Atomic int64_t reportedTotal = -1;
static _Atomic bool scriptDone = false;
static _Atomic int32_t errorCount = 0;
static int32_t nativeDone(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
(void)args;
(void)argCount;
(void)userData;
atomic_store(&scriptDone, true);
calogValueNil(result);
return calogOkE;
}
static int32_t nativeReport(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
(void)userData;
calogValueNil(result);
if (argCount != 1 || args[0].type != calogIntE) {
return calogFail(result, calogErrArgE, "report expects one integer");
}
atomic_store(&reportedTotal, args[0].as.i);
return calogOkE;
}
static void onError(uint64_t contextId, const char *message, void *userData) {
(void)contextId;
(void)userData;
fprintf(stderr, "script error: %s\n", (message != NULL) ? message : "(null)");
atomic_fetch_add(&errorCount, 1);
}
int main(void) {
CalogT *calog;
CalogContextT *ctx;
struct timespec tick = { 0, 1000000 };
int i;
calog = calogCreate();
if (calog == NULL) {
printf("calog create failed\n");
return 1;
}
calogSetErrorHandler(calog, onError, NULL);
calogRegister(calog, "report", nativeReport, NULL);
calogRegister(calog, "done", nativeDone, NULL);
if (calogDbRegister(calog) != calogOkE || calogNetRegister(calog) != calogOkE) {
printf("library registration failed\n");
return 1;
}
ctx = calogContextOpen(calog, &calogLuaEngine);
if (ctx == NULL) {
printf("context open failed\n");
calogDestroy(calog);
calogDbShutdown();
calogNetShutdown();
return 1;
}
calogContextEval(ctx,
"local db = dbOpen('sqlite', ':memory:')\n"
"dbExec(db, 'create table n (v integer)')\n"
"for i = 1, 10 do dbExec(db, 'insert into n values (?)', i) end\n"
"local rows = dbQuery(db, 'select sum(v) as total from n')\n"
"local total = rows[1].total\n"
"dbClose(db)\n"
"local s = udpOpen(0)\n"
"udpClose(s)\n"
"report(total)\n"
"done()");
for (i = 0; i < 2000 && !atomic_load(&scriptDone) && atomic_load(&errorCount) == 0; i++) {
calogPump(calog);
nanosleep(&tick, NULL);
}
calogPump(calog);
calogContextClose(ctx);
calogDestroy(calog);
calogDbShutdown();
calogNetShutdown();
if (atomic_load(&reportedTotal) != 55) {
printf("FAILED: expected 55, got %lld\n", (long long)atomic_load(&reportedTotal));
return 1;
}
printf("static calog app OK: SQLite summed 1..10 = %lld, UDP socket opened + closed\n", (long long)atomic_load(&reportedTotal));
return 0;
}

1099
libs/calogDb.c Normal file

File diff suppressed because it is too large Load diff

41
libs/calogDb.h Normal file
View file

@ -0,0 +1,41 @@
// calogDb.h -- calog database library.
//
// Registers a small set of inline natives that a script of any engine can call:
// dbOpen(driver, conn) -> handle (driver: "sqlite" / "postgres" / "mysql")
// dbExec(handle, sql, ...params) -> rowsAffected
// dbQuery(handle, sql, ...params) -> list of {column: value} row maps
// dbClose(handle)
// Values marshal by CalogValueT: NULL <-> nil, integers/reals as-is, text and BLOBs as
// binary-safe strings. Parameters are always BOUND (never string-spliced), so scripts are
// injection-safe by construction. The natives are INLINE -- a slow query blocks only the
// calling script's context thread, not the host. Backends are compiled in with
// CALOG_WITH_SQLITE / _PG / _MYSQL.
//
// Ownership: a connection handle belongs to the context that opened it. Handles are NOT
// reference-counted, so it is undefined behaviour for two contexts to use the same handle
// concurrently, or for one context to close a handle while another is mid-operation on it
// (a use-after-free, exactly as with a raw file descriptor). Pass work between contexts,
// not live handles.
//
// Connection strings:
// sqlite -- a file path, or ":memory:".
// postgres -- a libpq conninfo, e.g. "host=/tmp dbname=app user=me". TLS follows libpq
// (default sslmode=prefer: use TLS if offered, else plain, no verification).
// mysql -- "key=value ..." over host/user/password/dbname/port/socket, plus sslmode
// (default "prefer": TLS if offered else plain, no verification; "disable" =
// plain; "require" = TLS + server-certificate verification).
#ifndef CALOG_DB_H
#define CALOG_DB_H
#include "calog.h"
// Register the DB natives on a runtime. Idempotent across runtimes (they share a
// process-wide connection registry). Returns calogOkE or an error.
int32_t calogDbRegister(CalogT *calog);
// Close any still-open connections and free the process-wide DB registry. Call it AFTER
// the runtime is torn down (calogDestroy), since it invalidates the natives' state.
void calogDbShutdown(void);
#endif

204
libs/calogExport.c Normal file
View file

@ -0,0 +1,204 @@
// calogExport.c -- calog export library (see calogExport.h). A process-wide, mutex-guarded
// map of name -> reference-counted function value. export/unexport/call are natives;
// __exportResolve is the hook the per-engine dynamic-name resolvers call to look a name up.
//
// The registry state is STATIC (not heap), and never freed: the four natives are reachable
// (via any context, and via every Lua unknown-global lookup) right up until calogDestroy
// tears the broker registry down, so freeing the state in calogExportShutdown -- which the
// contract requires BEFORE calogDestroy -- would leave those natives dereferencing freed
// memory. calogExportShutdown instead just releases the exported functions and empties the
// map; the small static bookkeeping persists for the process (no per-cycle leak).
#define _POSIX_C_SOURCE 200809L
#include "calogExport.h"
#include <pthread.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#define EXPORT_INITIAL_CAP 8
#define EXPORT_GROWTH 2
typedef struct ExportEntryT {
char *name;
CalogFnT *fn;
} ExportEntryT;
// The map (heap array), guarded by gMapMutex. refCount (guarded by gInitMutex) counts
// registered runtimes so the LAST calogExportShutdown empties the map.
static pthread_mutex_t gMapMutex = PTHREAD_MUTEX_INITIALIZER;
static ExportEntryT *gEntries = NULL;
static int32_t gCount = 0;
static int32_t gCap = 0;
static pthread_mutex_t gInitMutex = PTHREAD_MUTEX_INITIALIZER;
static int32_t gRefCount = 0;
static int32_t exportCall(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t exportFindLocked(const char *name);
static int32_t exportPublish(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t exportRemove(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t exportResolve(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
int32_t calogExportRegister(CalogT *calog) {
pthread_mutex_lock(&gInitMutex);
gRefCount++;
pthread_mutex_unlock(&gInitMutex);
calogRegisterInline(calog, "export", exportPublish, NULL);
calogRegisterInline(calog, "unexport", exportRemove, NULL);
calogRegisterInline(calog, "call", exportCall, NULL);
calogRegisterInline(calog, "__exportResolve", exportResolve, NULL);
return calogOkE;
}
void calogExportShutdown(void) {
pthread_mutex_lock(&gInitMutex);
if (gRefCount > 0) {
gRefCount--;
}
if (gRefCount <= 0) {
int32_t index;
pthread_mutex_lock(&gMapMutex);
for (index = 0; index < gCount; index++) {
free(gEntries[index].name);
calogFnRelease(gEntries[index].fn);
}
free(gEntries);
gEntries = NULL;
gCount = 0;
gCap = 0;
pthread_mutex_unlock(&gMapMutex);
}
pthread_mutex_unlock(&gInitMutex);
}
static int32_t exportCall(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
CalogFnT *fn;
int32_t index;
int32_t status;
(void)userData;
calogValueNil(result);
if (argCount < 1 || args[0].type != calogStringE) {
return calogFail(result, calogErrArgE, "call expects (name, ...args)");
}
pthread_mutex_lock(&gMapMutex);
index = exportFindLocked(args[0].as.s.bytes);
if (index < 0) {
pthread_mutex_unlock(&gMapMutex);
return calogFail(result, calogErrNotFoundE, "call: no such exported function");
}
// Hold a reference across the (unlocked) call so a concurrent unexport can't free it.
fn = gEntries[index].fn;
calogFnRetain(fn);
pthread_mutex_unlock(&gMapMutex);
status = calogFnInvoke(fn, &args[1], argCount - 1, result);
calogFnRelease(fn);
return status;
}
static int32_t exportFindLocked(const char *name) {
int32_t index;
for (index = 0; index < gCount; index++) {
if (strcmp(gEntries[index].name, name) == 0) {
return index;
}
}
return -1;
}
static int32_t exportPublish(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
const char *name;
char *nameCopy;
int32_t index;
(void)userData;
calogValueNil(result);
if (argCount != 2 || args[0].type != calogStringE || args[1].type != calogFnE) {
return calogFail(result, calogErrArgE, "export expects (name, function)");
}
name = args[0].as.s.bytes;
pthread_mutex_lock(&gMapMutex);
index = exportFindLocked(name);
if (index >= 0) {
// Replace: drop the old function, retain the new one.
calogFnRelease(gEntries[index].fn);
calogFnRetain(args[1].as.fn);
gEntries[index].fn = args[1].as.fn;
pthread_mutex_unlock(&gMapMutex);
return calogOkE;
}
if (gCount == gCap) {
int32_t newCap;
ExportEntryT *grown;
newCap = (gCap == 0) ? EXPORT_INITIAL_CAP : gCap * EXPORT_GROWTH;
grown = (ExportEntryT *)realloc(gEntries, (size_t)newCap * sizeof(ExportEntryT));
if (grown == NULL) {
pthread_mutex_unlock(&gMapMutex);
return calogFail(result, calogErrOomE, "export: out of memory");
}
gEntries = grown;
gCap = newCap;
}
nameCopy = strdup(name);
if (nameCopy == NULL) {
pthread_mutex_unlock(&gMapMutex);
return calogFail(result, calogErrOomE, "export: out of memory");
}
calogFnRetain(args[1].as.fn);
gEntries[gCount].name = nameCopy;
gEntries[gCount].fn = args[1].as.fn;
gCount++;
pthread_mutex_unlock(&gMapMutex);
return calogOkE;
}
static int32_t exportRemove(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
int32_t index;
(void)userData;
calogValueNil(result);
if (argCount != 1 || args[0].type != calogStringE) {
return calogFail(result, calogErrArgE, "unexport expects (name)");
}
pthread_mutex_lock(&gMapMutex);
index = exportFindLocked(args[0].as.s.bytes);
if (index >= 0) {
free(gEntries[index].name);
calogFnRelease(gEntries[index].fn);
gEntries[index] = gEntries[gCount - 1];
gCount--;
}
pthread_mutex_unlock(&gMapMutex);
return calogOkE;
}
static int32_t exportResolve(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
int32_t index;
(void)userData;
calogValueNil(result);
if (argCount != 1 || args[0].type != calogStringE) {
return calogFail(result, calogErrArgE, "__exportResolve expects (name)");
}
pthread_mutex_lock(&gMapMutex);
index = exportFindLocked(args[0].as.s.bytes);
if (index >= 0) {
CalogFnT *fn;
fn = gEntries[index].fn;
// The result carries a reference; whoever consumes it releases that reference.
calogFnRetain(fn);
calogValueFn(result, fn);
}
pthread_mutex_unlock(&gMapMutex);
return calogOkE;
}

39
libs/calogExport.h Normal file
View file

@ -0,0 +1,39 @@
// calogExport.h -- calog export library: publish script functions other scripts can call.
//
// Registers natives so a script can share a function by name across contexts and engines:
// export(name, fn) publish a function value under a global name
// unexport(name) remove it
// call(name, ...args) call an exported function by name -- works in EVERY engine
//
// On engines with a runtime unknown-name hook (Lua, Squirrel, JavaScript, s7), an exported
// name is ALSO reachable by its BARE name, e.g. `luaExample(1, 2)`; engines that resolve
// names statically (Wren, Berry, my-basic) use call('luaExample', ...). Resolution is
// dynamic: a name exported at any time becomes callable immediately, and unexport takes
// effect at once.
//
// An exported function is an ordinary calog function value, so a call runs in the exporter's
// own context/thread (marshalled like any callable), and a call after the exporter is gone
// fails cleanly. The registry is process-wide and reference-counted across runtimes.
//
// NOTE (bare-name shadowing): on the hook engines, reading an otherwise-undefined global
// whose name matches an export resolves to that export -- an exported name is visible to
// every context, so pick export names that will not collide with scripts' feature-detection
// of undefined globals.
#ifndef CALOG_EXPORT_H
#define CALOG_EXPORT_H
#include "calog.h"
// Register the export natives on a runtime. Idempotent across runtimes (shared registry).
int32_t calogExportRegister(CalogT *calog);
// Release every exported function (once the last registered runtime unregisters). Unlike the
// other libraries, call this while the exporting contexts are still ALIVE -- before you close
// them and before calogDestroy -- because an exported function is a live reference into its
// owner's interpreter; releasing it after that context is gone would touch freed memory. The
// static registry bookkeeping itself is intentionally never freed (the natives stay callable
// until calogDestroy), so this is safe to call and re-register across runtimes.
void calogExportShutdown(void);
#endif

155
libs/calogHandle.c Normal file
View file

@ -0,0 +1,155 @@
// calogHandle.c -- thread-safe, typed integer handle table (see calogHandle.h).
#include "calogHandle.h"
#include <pthread.h>
#include <stdlib.h>
#define HANDLE_INITIAL_CAP 8
#define HANDLE_GROWTH 2
// A free slot has handle == 0; the monotonic nextHandle starts at 1, so 0 is never a
// live handle and doubles as the "invalid" sentinel a caller can test.
typedef struct HandleEntryT {
int64_t handle;
uint32_t type;
void *resource;
} HandleEntryT;
struct CalogHandleTableT {
pthread_mutex_t mutex;
HandleEntryT *entries;
int32_t count;
int32_t cap;
int64_t nextHandle;
};
int64_t calogHandleAdd(CalogHandleTableT *table, uint32_t type, void *resource) {
int64_t handle;
int32_t slot;
int32_t index;
pthread_mutex_lock(&table->mutex);
slot = -1;
for (index = 0; index < table->count; index++) {
if (table->entries[index].handle == 0) {
slot = index;
break;
}
}
if (slot < 0) {
if (table->count == table->cap) {
int32_t newCap;
HandleEntryT *grown;
newCap = (table->cap == 0) ? HANDLE_INITIAL_CAP : table->cap * HANDLE_GROWTH;
grown = (HandleEntryT *)realloc(table->entries, (size_t)newCap * sizeof(HandleEntryT));
if (grown == NULL) {
pthread_mutex_unlock(&table->mutex);
return 0;
}
table->entries = grown;
table->cap = newCap;
}
slot = table->count;
table->count++;
}
handle = table->nextHandle;
table->nextHandle++;
table->entries[slot].handle = handle;
table->entries[slot].type = type;
table->entries[slot].resource = resource;
pthread_mutex_unlock(&table->mutex);
return handle;
}
int32_t calogHandleCount(CalogHandleTableT *table, uint32_t type) {
int32_t count;
int32_t index;
count = 0;
pthread_mutex_lock(&table->mutex);
for (index = 0; index < table->count; index++) {
if (table->entries[index].handle != 0 && table->entries[index].type == type) {
count++;
}
}
pthread_mutex_unlock(&table->mutex);
return count;
}
void *calogHandleGet(CalogHandleTableT *table, int64_t handle, uint32_t type) {
void *resource;
int32_t index;
// Valid handles are >= 1; reject 0 (the free-slot sentinel) and negatives so a bogus or
// zero handle can never alias a freed slot.
if (handle <= 0) {
return NULL;
}
resource = NULL;
pthread_mutex_lock(&table->mutex);
for (index = 0; index < table->count; index++) {
if (table->entries[index].handle == handle && table->entries[index].type == type) {
resource = table->entries[index].resource;
break;
}
}
pthread_mutex_unlock(&table->mutex);
return resource;
}
void *calogHandleRemove(CalogHandleTableT *table, int64_t handle, uint32_t type) {
void *resource;
int32_t index;
if (handle <= 0) {
return NULL;
}
resource = NULL;
pthread_mutex_lock(&table->mutex);
for (index = 0; index < table->count; index++) {
if (table->entries[index].handle == handle && table->entries[index].type == type) {
resource = table->entries[index].resource;
table->entries[index].handle = 0;
table->entries[index].type = 0;
table->entries[index].resource = NULL;
break;
}
}
pthread_mutex_unlock(&table->mutex);
return resource;
}
CalogHandleTableT *calogHandleTableCreate(void) {
CalogHandleTableT *table;
table = (CalogHandleTableT *)calloc(1, sizeof(*table));
if (table == NULL) {
return NULL;
}
pthread_mutex_init(&table->mutex, NULL);
table->nextHandle = 1;
return table;
}
void calogHandleTableDestroy(CalogHandleTableT *table, CalogHandleCloserT closer) {
int32_t index;
if (table == NULL) {
return;
}
for (index = 0; index < table->count; index++) {
if (table->entries[index].handle != 0 && closer != NULL) {
closer(table->entries[index].type, table->entries[index].resource);
}
}
free(table->entries);
pthread_mutex_destroy(&table->mutex);
free(table);
}

33
libs/calogHandle.h Normal file
View file

@ -0,0 +1,33 @@
// calogHandle.h -- thread-safe, typed integer handle table for calog libraries.
//
// calog library natives (DB, network) are registered INLINE, so they run on whatever
// context thread called them -- many at once. A resource (a connection, a socket) is
// therefore handed to a script as an opaque int64 handle backed by this table, which is
// mutex-guarded and tags every entry with a type so a DB handle can never be used where a
// socket is expected. Handles are monotonic and never reused, so a stale handle from a
// closed resource reliably fails to resolve rather than aliasing a live one.
#ifndef CALOG_HANDLE_H
#define CALOG_HANDLE_H
#include <stdint.h>
typedef struct CalogHandleTableT CalogHandleTableT;
// Invoked for each still-open entry at table destroy, to release the resource.
typedef void (*CalogHandleCloserT)(uint32_t type, void *resource);
// Add returns a positive handle, or 0 on out-of-memory. Get/Remove return the resource
// only when the handle exists AND its type matches; otherwise NULL. Remove also frees the
// slot. Destroy closes every remaining entry through the closer (may be NULL) and frees
// the table.
CalogHandleTableT *calogHandleTableCreate(void);
void calogHandleTableDestroy(CalogHandleTableT *table, CalogHandleCloserT closer);
int64_t calogHandleAdd(CalogHandleTableT *table, uint32_t type, void *resource);
void *calogHandleGet(CalogHandleTableT *table, int64_t handle, uint32_t type);
void *calogHandleRemove(CalogHandleTableT *table, int64_t handle, uint32_t type);
// Number of live entries of the given type currently in the table.
int32_t calogHandleCount(CalogHandleTableT *table, uint32_t type);
#endif

855
libs/calogNet.c Normal file
View file

@ -0,0 +1,855 @@
// calogNet.c -- calog network library (see calogNet.h). TCP + UDP for v1 over the shared
// typed handle table; every blocking call is an inline native, so it stalls only the
// calling script's context thread.
#define _GNU_SOURCE
#include "calogNet.h"
#include "calogHandle.h"
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#ifdef CALOG_WITH_ENET
#include <enet/enet.h>
#endif
// Handle type tags, distinct across the whole registry so a stray handle of the wrong kind
// fails to resolve (e.g. a listener passed to tcpSend).
#define NET_TYPE_TCP 1u
#define NET_TYPE_TCP_LISTEN 2u
#define NET_TYPE_UDP 3u
#define NET_TYPE_ENET_HOST 4u
#define NET_TYPE_ENET_PEER 5u
// Upper bound on a single recv/recvFrom allocation, so a script cannot request an arbitrary
// buffer size.
#define NET_MAX_RECV (64 * 1024 * 1024)
#define NET_PORT_MAX 65535
typedef struct NetSocketT {
int fd;
} NetSocketT;
// Process-wide network library state shared by every runtime that registers the natives.
typedef struct NetLibT {
CalogHandleTableT *handles;
int32_t refCount;
} NetLibT;
static pthread_mutex_t gNetLibMutex = PTHREAD_MUTEX_INITIALIZER;
static NetLibT *gNetLib = NULL;
#ifdef CALOG_WITH_ENET
static int32_t enetClose(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t enetConnect(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t enetDisconnect(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t enetHost(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t enetSend(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t enetService(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
#endif
static void netCloser(uint32_t type, void *resource);
static int32_t netMapSetInt(CalogAggT *map, const char *key, int64_t value);
static int32_t netMapSetStr(CalogAggT *map, const char *key, const char *bytes, int64_t length);
static int32_t netOpenBound(uint16_t port, int socktype, bool doListen, CalogValueT *result, int *fdOut);
static int netResolve(const char *host, uint16_t port, int socktype, bool passive, struct addrinfo **out);
static int32_t netStore(NetLibT *lib, int fd, uint32_t type, CalogValueT *result);
static int32_t tcpAccept(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t tcpClose(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t tcpConnect(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t tcpListen(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t tcpRecv(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t tcpSend(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t udpClose(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t udpOpen(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t udpRecvFrom(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t udpSendTo(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
int32_t calogNetRegister(CalogT *calog) {
pthread_mutex_lock(&gNetLibMutex);
if (gNetLib == NULL) {
NetLibT *lib;
lib = (NetLibT *)calloc(1, sizeof(*lib));
if (lib == NULL) {
pthread_mutex_unlock(&gNetLibMutex);
return calogErrOomE;
}
lib->handles = calogHandleTableCreate();
if (lib->handles == NULL) {
free(lib);
pthread_mutex_unlock(&gNetLibMutex);
return calogErrOomE;
}
#ifdef CALOG_WITH_ENET
if (enet_initialize() != 0) {
calogHandleTableDestroy(lib->handles, NULL);
free(lib);
pthread_mutex_unlock(&gNetLibMutex);
return calogErrOomE;
}
#endif
gNetLib = lib;
}
gNetLib->refCount++;
pthread_mutex_unlock(&gNetLibMutex);
calogRegisterInline(calog, "tcpConnect", tcpConnect, gNetLib);
calogRegisterInline(calog, "tcpListen", tcpListen, gNetLib);
calogRegisterInline(calog, "tcpAccept", tcpAccept, gNetLib);
calogRegisterInline(calog, "tcpSend", tcpSend, gNetLib);
calogRegisterInline(calog, "tcpRecv", tcpRecv, gNetLib);
calogRegisterInline(calog, "tcpClose", tcpClose, gNetLib);
calogRegisterInline(calog, "udpOpen", udpOpen, gNetLib);
calogRegisterInline(calog, "udpSendTo", udpSendTo, gNetLib);
calogRegisterInline(calog, "udpRecvFrom", udpRecvFrom, gNetLib);
calogRegisterInline(calog, "udpClose", udpClose, gNetLib);
#ifdef CALOG_WITH_ENET
calogRegisterInline(calog, "enetHost", enetHost, gNetLib);
calogRegisterInline(calog, "enetConnect", enetConnect, gNetLib);
calogRegisterInline(calog, "enetService", enetService, gNetLib);
calogRegisterInline(calog, "enetSend", enetSend, gNetLib);
calogRegisterInline(calog, "enetDisconnect", enetDisconnect, gNetLib);
calogRegisterInline(calog, "enetClose", enetClose, gNetLib);
#endif
return calogOkE;
}
void calogNetShutdown(void) {
pthread_mutex_lock(&gNetLibMutex);
if (gNetLib == NULL) {
pthread_mutex_unlock(&gNetLibMutex);
return;
}
gNetLib->refCount--;
if (gNetLib->refCount <= 0) {
calogHandleTableDestroy(gNetLib->handles, netCloser);
#ifdef CALOG_WITH_ENET
enet_deinitialize();
#endif
free(gNetLib);
gNetLib = NULL;
}
pthread_mutex_unlock(&gNetLibMutex);
}
static void netCloser(uint32_t type, void *resource) {
switch (type) {
case NET_TYPE_TCP:
case NET_TYPE_TCP_LISTEN:
case NET_TYPE_UDP: {
NetSocketT *sock;
sock = (NetSocketT *)resource;
close(sock->fd);
free(sock);
break;
}
#ifdef CALOG_WITH_ENET
case NET_TYPE_ENET_HOST:
enet_host_destroy((ENetHost *)resource);
break;
case NET_TYPE_ENET_PEER:
// Peers are owned by their host; enet_host_destroy frees them.
break;
#endif
default:
break;
}
}
// Set map[key] = integer. On failure the (freshly built) key is released; the scalar value
// needs none.
static int32_t netMapSetInt(CalogAggT *map, const char *key, int64_t value) {
CalogValueT keyValue;
CalogValueT intValue;
int32_t status;
status = calogValueString(&keyValue, key, (int64_t)strlen(key));
if (status != calogOkE) {
return status;
}
calogValueInt(&intValue, value);
status = calogAggSet(map, &keyValue, &intValue);
if (status != calogOkE) {
calogValueFree(&keyValue);
}
return status;
}
// Set map[key] = binary-safe string. On failure any built values are released.
static int32_t netMapSetStr(CalogAggT *map, const char *key, const char *bytes, int64_t length) {
CalogValueT keyValue;
CalogValueT stringValue;
int32_t status;
status = calogValueString(&keyValue, key, (int64_t)strlen(key));
if (status != calogOkE) {
return status;
}
status = calogValueString(&stringValue, bytes, length);
if (status != calogOkE) {
calogValueFree(&keyValue);
return status;
}
status = calogAggSet(map, &keyValue, &stringValue);
if (status != calogOkE) {
calogValueFree(&keyValue);
calogValueFree(&stringValue);
}
return status;
}
// Create a socket bound to the given local port (0 = ephemeral), optionally listening.
// Returns calogOkE with *fdOut set, or an error with result populated.
static int32_t netOpenBound(uint16_t port, int socktype, bool doListen, CalogValueT *result, int *fdOut) {
struct addrinfo *res;
struct addrinfo *rp;
int fd;
int rc;
int yes;
*fdOut = -1;
yes = 1;
rc = netResolve(NULL, port, socktype, true, &res);
if (rc != 0) {
return calogFail(result, calogErrArgE, gai_strerror(rc));
}
fd = -1;
for (rp = res; rp != NULL; rp = rp->ai_next) {
fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (fd < 0) {
continue;
}
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
if (bind(fd, rp->ai_addr, rp->ai_addrlen) == 0) {
break;
}
close(fd);
fd = -1;
}
freeaddrinfo(res);
if (fd < 0) {
return calogFail(result, calogErrArgE, "could not bind the requested port");
}
if (doListen && listen(fd, SOMAXCONN) != 0) {
int32_t status;
status = calogFail(result, calogErrArgE, strerror(errno));
close(fd);
return status;
}
*fdOut = fd;
return calogOkE;
}
static int netResolve(const char *host, uint16_t port, int socktype, bool passive, struct addrinfo **out) {
struct addrinfo hints;
char portBuffer[8];
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = socktype;
if (passive) {
hints.ai_flags = AI_PASSIVE;
}
snprintf(portBuffer, sizeof(portBuffer), "%u", (unsigned int)port);
return getaddrinfo(host, portBuffer, &hints, out);
}
// Wrap an open fd in a handle-table entry, transferring ownership. On failure the fd is
// closed. Sets result to the new integer handle on success.
static int32_t netStore(NetLibT *lib, int fd, uint32_t type, CalogValueT *result) {
NetSocketT *sock;
int64_t handle;
sock = (NetSocketT *)malloc(sizeof(*sock));
if (sock == NULL) {
close(fd);
return calogFail(result, calogErrOomE, "out of memory");
}
sock->fd = fd;
handle = calogHandleAdd(lib->handles, type, sock);
if (handle == 0) {
close(fd);
free(sock);
return calogFail(result, calogErrOomE, "out of memory");
}
calogValueInt(result, handle);
return calogOkE;
}
static int32_t tcpAccept(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
NetLibT *lib;
NetSocketT *listener;
int fd;
lib = (NetLibT *)userData;
calogValueNil(result);
if (argCount != 1 || args[0].type != calogIntE) {
return calogFail(result, calogErrArgE, "tcpAccept expects (listenerHandle)");
}
listener = (NetSocketT *)calogHandleGet(lib->handles, args[0].as.i, NET_TYPE_TCP_LISTEN);
if (listener == NULL) {
return calogFail(result, calogErrArgE, "tcpAccept: invalid listener handle");
}
fd = accept(listener->fd, NULL, NULL);
if (fd < 0) {
return calogFail(result, calogErrArgE, strerror(errno));
}
return netStore(lib, fd, NET_TYPE_TCP, result);
}
static int32_t tcpClose(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
NetLibT *lib;
NetSocketT *sock;
lib = (NetLibT *)userData;
calogValueNil(result);
if (argCount != 1 || args[0].type != calogIntE) {
return calogFail(result, calogErrArgE, "tcpClose expects (handle)");
}
sock = (NetSocketT *)calogHandleRemove(lib->handles, args[0].as.i, NET_TYPE_TCP);
if (sock == NULL) {
sock = (NetSocketT *)calogHandleRemove(lib->handles, args[0].as.i, NET_TYPE_TCP_LISTEN);
}
if (sock == NULL) {
return calogFail(result, calogErrArgE, "tcpClose: invalid handle");
}
close(sock->fd);
free(sock);
return calogOkE;
}
static int32_t tcpConnect(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
NetLibT *lib;
struct addrinfo *res;
struct addrinfo *rp;
int fd;
int rc;
lib = (NetLibT *)userData;
calogValueNil(result);
if (argCount != 2 || args[0].type != calogStringE || args[1].type != calogIntE) {
return calogFail(result, calogErrArgE, "tcpConnect expects (host, port)");
}
if (args[1].as.i < 0 || args[1].as.i > NET_PORT_MAX) {
return calogFail(result, calogErrArgE, "tcpConnect: port out of range");
}
rc = netResolve(args[0].as.s.bytes, (uint16_t)args[1].as.i, SOCK_STREAM, false, &res);
if (rc != 0) {
return calogFail(result, calogErrArgE, gai_strerror(rc));
}
fd = -1;
for (rp = res; rp != NULL; rp = rp->ai_next) {
fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (fd < 0) {
continue;
}
if (connect(fd, rp->ai_addr, rp->ai_addrlen) == 0) {
break;
}
close(fd);
fd = -1;
}
freeaddrinfo(res);
if (fd < 0) {
return calogFail(result, calogErrArgE, "tcpConnect: could not connect");
}
return netStore(lib, fd, NET_TYPE_TCP, result);
}
static int32_t tcpListen(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
NetLibT *lib;
int fd;
int32_t status;
lib = (NetLibT *)userData;
calogValueNil(result);
if (argCount != 1 || args[0].type != calogIntE) {
return calogFail(result, calogErrArgE, "tcpListen expects (port)");
}
if (args[0].as.i < 0 || args[0].as.i > NET_PORT_MAX) {
return calogFail(result, calogErrArgE, "tcpListen: port out of range");
}
status = netOpenBound((uint16_t)args[0].as.i, SOCK_STREAM, true, result, &fd);
if (status != calogOkE) {
return status;
}
return netStore(lib, fd, NET_TYPE_TCP_LISTEN, result);
}
static int32_t tcpRecv(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
NetLibT *lib;
NetSocketT *sock;
char *buffer;
ssize_t received;
int32_t status;
lib = (NetLibT *)userData;
calogValueNil(result);
if (argCount != 2 || args[0].type != calogIntE || args[1].type != calogIntE) {
return calogFail(result, calogErrArgE, "tcpRecv expects (handle, maxBytes)");
}
if (args[1].as.i < 1 || args[1].as.i > NET_MAX_RECV) {
return calogFail(result, calogErrArgE, "tcpRecv: maxBytes out of range");
}
sock = (NetSocketT *)calogHandleGet(lib->handles, args[0].as.i, NET_TYPE_TCP);
if (sock == NULL) {
return calogFail(result, calogErrArgE, "tcpRecv: invalid handle");
}
buffer = (char *)malloc((size_t)args[1].as.i);
if (buffer == NULL) {
return calogFail(result, calogErrOomE, "tcpRecv: out of memory");
}
received = recv(sock->fd, buffer, (size_t)args[1].as.i, 0);
if (received < 0) {
status = calogFail(result, calogErrArgE, strerror(errno));
free(buffer);
return status;
}
if (received == 0) {
// Peer closed the connection: nil signals end of stream.
free(buffer);
return calogOkE;
}
status = calogValueString(result, buffer, (int64_t)received);
free(buffer);
return status;
}
static int32_t tcpSend(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
NetLibT *lib;
NetSocketT *sock;
int64_t total;
lib = (NetLibT *)userData;
calogValueNil(result);
if (argCount != 2 || args[0].type != calogIntE || args[1].type != calogStringE) {
return calogFail(result, calogErrArgE, "tcpSend expects (handle, data)");
}
sock = (NetSocketT *)calogHandleGet(lib->handles, args[0].as.i, NET_TYPE_TCP);
if (sock == NULL) {
return calogFail(result, calogErrArgE, "tcpSend: invalid handle");
}
total = 0;
while (total < args[1].as.s.length) {
ssize_t sent;
sent = send(sock->fd, args[1].as.s.bytes + total, (size_t)(args[1].as.s.length - total), MSG_NOSIGNAL);
if (sent < 0) {
return calogFail(result, calogErrArgE, strerror(errno));
}
total += sent;
}
calogValueInt(result, total);
return calogOkE;
}
static int32_t udpClose(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
NetLibT *lib;
NetSocketT *sock;
lib = (NetLibT *)userData;
calogValueNil(result);
if (argCount != 1 || args[0].type != calogIntE) {
return calogFail(result, calogErrArgE, "udpClose expects (handle)");
}
sock = (NetSocketT *)calogHandleRemove(lib->handles, args[0].as.i, NET_TYPE_UDP);
if (sock == NULL) {
return calogFail(result, calogErrArgE, "udpClose: invalid handle");
}
close(sock->fd);
free(sock);
return calogOkE;
}
static int32_t udpOpen(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
NetLibT *lib;
int fd;
int32_t status;
lib = (NetLibT *)userData;
calogValueNil(result);
if (argCount != 1 || args[0].type != calogIntE) {
return calogFail(result, calogErrArgE, "udpOpen expects (port)");
}
if (args[0].as.i < 0 || args[0].as.i > NET_PORT_MAX) {
return calogFail(result, calogErrArgE, "udpOpen: port out of range");
}
status = netOpenBound((uint16_t)args[0].as.i, SOCK_DGRAM, false, result, &fd);
if (status != calogOkE) {
return status;
}
return netStore(lib, fd, NET_TYPE_UDP, result);
}
static int32_t udpRecvFrom(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
NetLibT *lib;
NetSocketT *sock;
CalogAggT *map;
char *buffer;
struct sockaddr_in from;
socklen_t fromLength;
ssize_t received;
char hostBuffer[INET_ADDRSTRLEN];
int32_t status;
lib = (NetLibT *)userData;
calogValueNil(result);
if (argCount != 2 || args[0].type != calogIntE || args[1].type != calogIntE) {
return calogFail(result, calogErrArgE, "udpRecvFrom expects (handle, maxBytes)");
}
if (args[1].as.i < 1 || args[1].as.i > NET_MAX_RECV) {
return calogFail(result, calogErrArgE, "udpRecvFrom: maxBytes out of range");
}
sock = (NetSocketT *)calogHandleGet(lib->handles, args[0].as.i, NET_TYPE_UDP);
if (sock == NULL) {
return calogFail(result, calogErrArgE, "udpRecvFrom: invalid handle");
}
buffer = (char *)malloc((size_t)args[1].as.i);
if (buffer == NULL) {
return calogFail(result, calogErrOomE, "udpRecvFrom: out of memory");
}
fromLength = sizeof(from);
received = recvfrom(sock->fd, buffer, (size_t)args[1].as.i, 0, (struct sockaddr *)&from, &fromLength);
if (received < 0) {
status = calogFail(result, calogErrArgE, strerror(errno));
free(buffer);
return status;
}
if (inet_ntop(AF_INET, &from.sin_addr, hostBuffer, sizeof(hostBuffer)) == NULL) {
hostBuffer[0] = '\0';
}
status = calogAggCreate(&map, calogMapE);
if (status != calogOkE) {
free(buffer);
return calogFail(result, status, "udpRecvFrom: out of memory");
}
status = netMapSetStr(map, "data", buffer, (int64_t)received);
free(buffer);
if (status == calogOkE) {
status = netMapSetStr(map, "host", hostBuffer, (int64_t)strlen(hostBuffer));
}
if (status == calogOkE) {
status = netMapSetInt(map, "port", (int64_t)ntohs(from.sin_port));
}
if (status != calogOkE) {
calogAggFree(map);
return calogFail(result, status, "udpRecvFrom: failed to build the result");
}
calogValueAgg(result, map);
return calogOkE;
}
static int32_t udpSendTo(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
NetLibT *lib;
NetSocketT *sock;
struct addrinfo *res;
ssize_t sent;
int rc;
lib = (NetLibT *)userData;
calogValueNil(result);
if (argCount != 4 || args[0].type != calogIntE || args[1].type != calogStringE || args[2].type != calogIntE || args[3].type != calogStringE) {
return calogFail(result, calogErrArgE, "udpSendTo expects (handle, host, port, data)");
}
if (args[2].as.i < 0 || args[2].as.i > NET_PORT_MAX) {
return calogFail(result, calogErrArgE, "udpSendTo: port out of range");
}
sock = (NetSocketT *)calogHandleGet(lib->handles, args[0].as.i, NET_TYPE_UDP);
if (sock == NULL) {
return calogFail(result, calogErrArgE, "udpSendTo: invalid handle");
}
rc = netResolve(args[1].as.s.bytes, (uint16_t)args[2].as.i, SOCK_DGRAM, false, &res);
if (rc != 0) {
return calogFail(result, calogErrArgE, gai_strerror(rc));
}
sent = sendto(sock->fd, args[3].as.s.bytes, (size_t)args[3].as.s.length, 0, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
if (sent < 0) {
return calogFail(result, calogErrArgE, strerror(errno));
}
calogValueInt(result, (int64_t)sent);
return calogOkE;
}
#ifdef CALOG_WITH_ENET
static int32_t enetClose(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
NetLibT *lib;
ENetHost *host;
lib = (NetLibT *)userData;
calogValueNil(result);
if (argCount != 1 || args[0].type != calogIntE) {
return calogFail(result, calogErrArgE, "enetClose expects (hostHandle)");
}
host = (ENetHost *)calogHandleRemove(lib->handles, args[0].as.i, NET_TYPE_ENET_HOST);
if (host == NULL) {
return calogFail(result, calogErrArgE, "enetClose: invalid host handle");
}
// enet_host_destroy frees the peer array, so drop every outstanding peer handle for this
// host first -- otherwise those handles would resolve to freed memory (use-after-free).
{
size_t peerIndex;
for (peerIndex = 0; peerIndex < host->peerCount; peerIndex++) {
ENetPeer *peer;
int64_t peerHandle;
peer = &host->peers[peerIndex];
peerHandle = (int64_t)(intptr_t)peer->data;
if (peerHandle != 0) {
calogHandleRemove(lib->handles, peerHandle, NET_TYPE_ENET_PEER);
peer->data = NULL;
}
}
}
enet_host_destroy(host);
return calogOkE;
}
static int32_t enetConnect(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
NetLibT *lib;
ENetHost *host;
ENetPeer *peer;
ENetAddress address;
int64_t handle;
lib = (NetLibT *)userData;
calogValueNil(result);
if (argCount != 4 || args[0].type != calogIntE || args[1].type != calogStringE || args[2].type != calogIntE || args[3].type != calogIntE) {
return calogFail(result, calogErrArgE, "enetConnect expects (hostHandle, host, port, channels)");
}
if (args[2].as.i < 0 || args[2].as.i > NET_PORT_MAX) {
return calogFail(result, calogErrArgE, "enetConnect: port out of range");
}
if (args[3].as.i < 1) {
return calogFail(result, calogErrArgE, "enetConnect: channels must be positive");
}
host = (ENetHost *)calogHandleGet(lib->handles, args[0].as.i, NET_TYPE_ENET_HOST);
if (host == NULL) {
return calogFail(result, calogErrArgE, "enetConnect: invalid host handle");
}
if (enet_address_set_host(&address, args[1].as.s.bytes) != 0) {
return calogFail(result, calogErrArgE, "enetConnect: could not resolve host");
}
address.port = (enet_uint16)args[2].as.i;
peer = enet_host_connect(host, &address, (size_t)args[3].as.i, 0);
if (peer == NULL) {
return calogFail(result, calogErrArgE, "enetConnect: no available peer slots");
}
handle = calogHandleAdd(lib->handles, NET_TYPE_ENET_PEER, peer);
if (handle == 0) {
enet_peer_reset(peer);
return calogFail(result, calogErrOomE, "enetConnect: out of memory");
}
peer->data = (void *)(intptr_t)handle;
calogValueInt(result, handle);
return calogOkE;
}
static int32_t enetDisconnect(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
NetLibT *lib;
ENetPeer *peer;
lib = (NetLibT *)userData;
calogValueNil(result);
if (argCount != 1 || args[0].type != calogIntE) {
return calogFail(result, calogErrArgE, "enetDisconnect expects (peerHandle)");
}
peer = (ENetPeer *)calogHandleGet(lib->handles, args[0].as.i, NET_TYPE_ENET_PEER);
if (peer == NULL) {
return calogFail(result, calogErrArgE, "enetDisconnect: invalid peer handle");
}
// Graceful: the actual removal happens when the disconnect event is serviced.
enet_peer_disconnect(peer, 0);
return calogOkE;
}
static int32_t enetHost(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
NetLibT *lib;
ENetHost *host;
ENetAddress address;
ENetAddress *addressPtr;
int64_t handle;
lib = (NetLibT *)userData;
calogValueNil(result);
if (argCount != 2 || args[0].type != calogIntE || args[1].type != calogIntE) {
return calogFail(result, calogErrArgE, "enetHost expects (port, maxPeers)");
}
if (args[0].as.i < 0 || args[0].as.i > NET_PORT_MAX) {
return calogFail(result, calogErrArgE, "enetHost: port out of range");
}
if (args[1].as.i < 1) {
return calogFail(result, calogErrArgE, "enetHost: maxPeers must be positive");
}
// port 0 -> a client host (no bind); port > 0 -> a server host bound to that port.
addressPtr = NULL;
if (args[0].as.i > 0) {
address.host = ENET_HOST_ANY;
address.port = (enet_uint16)args[0].as.i;
addressPtr = &address;
}
host = enet_host_create(addressPtr, (size_t)args[1].as.i, 0, 0, 0);
if (host == NULL) {
return calogFail(result, calogErrArgE, "enetHost: could not create host");
}
handle = calogHandleAdd(lib->handles, NET_TYPE_ENET_HOST, host);
if (handle == 0) {
enet_host_destroy(host);
return calogFail(result, calogErrOomE, "enetHost: out of memory");
}
calogValueInt(result, handle);
return calogOkE;
}
static int32_t enetSend(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
NetLibT *lib;
ENetPeer *peer;
ENetPacket *packet;
enet_uint32 flags;
lib = (NetLibT *)userData;
calogValueNil(result);
if (argCount != 4 || args[0].type != calogIntE || args[1].type != calogIntE || args[2].type != calogStringE || args[3].type != calogBoolE) {
return calogFail(result, calogErrArgE, "enetSend expects (peerHandle, channel, data, reliable)");
}
if (args[1].as.i < 0 || args[1].as.i > 255) {
return calogFail(result, calogErrArgE, "enetSend: channel out of range");
}
peer = (ENetPeer *)calogHandleGet(lib->handles, args[0].as.i, NET_TYPE_ENET_PEER);
if (peer == NULL) {
return calogFail(result, calogErrArgE, "enetSend: invalid peer handle");
}
flags = 0;
if (args[3].as.b) {
flags = (enet_uint32)ENET_PACKET_FLAG_RELIABLE;
}
packet = enet_packet_create(args[2].as.s.bytes, (size_t)args[2].as.s.length, flags);
if (packet == NULL) {
return calogFail(result, calogErrOomE, "enetSend: out of memory");
}
if (enet_peer_send(peer, (enet_uint8)args[1].as.i, packet) != 0) {
enet_packet_destroy(packet);
return calogFail(result, calogErrArgE, "enetSend: could not queue the packet");
}
return calogOkE;
}
static int32_t enetService(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
NetLibT *lib;
ENetHost *host;
ENetEvent event;
CalogAggT *map;
int64_t peerHandle;
int32_t status;
int serviced;
lib = (NetLibT *)userData;
calogValueNil(result);
if (argCount != 2 || args[0].type != calogIntE || args[1].type != calogIntE) {
return calogFail(result, calogErrArgE, "enetService expects (hostHandle, timeoutMs)");
}
if (args[1].as.i < 0) {
return calogFail(result, calogErrArgE, "enetService: timeout must be non-negative");
}
host = (ENetHost *)calogHandleGet(lib->handles, args[0].as.i, NET_TYPE_ENET_HOST);
if (host == NULL) {
return calogFail(result, calogErrArgE, "enetService: invalid host handle");
}
serviced = enet_host_service(host, &event, (enet_uint32)args[1].as.i);
if (serviced < 0) {
return calogFail(result, calogErrArgE, "enetService: service failed");
}
status = calogAggCreate(&map, calogMapE);
if (status != calogOkE) {
return calogFail(result, status, "enetService: out of memory");
}
if (serviced == 0 || event.type == ENET_EVENT_TYPE_NONE) {
status = netMapSetStr(map, "type", "none", 4);
if (status != calogOkE) {
calogAggFree(map);
return calogFail(result, status, "enetService: out of memory");
}
calogValueAgg(result, map);
return calogOkE;
}
// Every peer carries its stable handle in peer->data (0 = not yet assigned, e.g. a fresh
// incoming connection on a server host).
peerHandle = (int64_t)(intptr_t)event.peer->data;
if (peerHandle == 0) {
peerHandle = calogHandleAdd(lib->handles, NET_TYPE_ENET_PEER, event.peer);
if (peerHandle == 0) {
if (event.type == ENET_EVENT_TYPE_RECEIVE) {
enet_packet_destroy(event.packet);
}
calogAggFree(map);
return calogFail(result, calogErrOomE, "enetService: out of memory");
}
event.peer->data = (void *)(intptr_t)peerHandle;
}
switch (event.type) {
case ENET_EVENT_TYPE_CONNECT:
status = netMapSetStr(map, "type", "connect", 7);
break;
case ENET_EVENT_TYPE_RECEIVE:
status = netMapSetStr(map, "type", "receive", 7);
if (status == calogOkE) {
status = netMapSetInt(map, "channel", (int64_t)event.channelID);
}
if (status == calogOkE) {
status = netMapSetStr(map, "data", (const char *)event.packet->data, (int64_t)event.packet->dataLength);
}
enet_packet_destroy(event.packet);
break;
case ENET_EVENT_TYPE_DISCONNECT:
status = netMapSetStr(map, "type", "disconnect", 10);
// The peer is now invalid; drop its handle but still report it in this event.
calogHandleRemove(lib->handles, peerHandle, NET_TYPE_ENET_PEER);
event.peer->data = NULL;
break;
default:
status = netMapSetStr(map, "type", "none", 4);
break;
}
if (status == calogOkE) {
status = netMapSetInt(map, "peer", peerHandle);
}
if (status != calogOkE) {
calogAggFree(map);
return calogFail(result, status, "enetService: failed to build the event");
}
calogValueAgg(result, map);
return calogOkE;
}
#endif

36
libs/calogNet.h Normal file
View file

@ -0,0 +1,36 @@
// calogNet.h -- calog network library.
//
// Registers inline natives that a script of any engine can call:
// tcpConnect(host, port) -> handle
// tcpListen(port) -> handle
// tcpAccept(handle) -> handle (blocks for a client)
// tcpSend(handle, data) -> bytesSent (sends all of data)
// tcpRecv(handle, maxBytes) -> data (up to maxBytes; nil at end of stream)
// tcpClose(handle)
// udpOpen(port) -> handle (port 0 = ephemeral)
// udpSendTo(handle, host, port, data) -> bytesSent
// udpRecvFrom(handle, maxBytes) -> { data, host, port }
// udpClose(handle)
// Payloads are binary-safe strings. The blocking natives (accept/recv/recvFrom) are INLINE,
// so they stall only the calling script's context thread, not the host. Handles are NOT
// reference-counted: a socket/host/peer handle belongs to the context that created it, and
// using one handle concurrently from two contexts -- or closing it while another context is
// mid-operation -- is undefined (use-after-free). IPv4 for v1;
// hostname resolution uses getaddrinfo (works in dynamic builds; a fully-static glibc build
// cannot resolve names -- connect by IP, or link musl). Backends: TCP/UDP always; ENet is
// added behind CALOG_WITH_ENET.
#ifndef CALOG_NET_H
#define CALOG_NET_H
#include "calog.h"
// Register the network natives on a runtime. Idempotent across runtimes (they share a
// process-wide socket registry). Returns calogOkE or an error.
int32_t calogNetRegister(CalogT *calog);
// Close any still-open sockets and free the process-wide registry. Call it AFTER the
// runtime is torn down (calogDestroy), since it invalidates the natives' state.
void calogNetShutdown(void);
#endif

301
libs/calogTask.c Normal file
View file

@ -0,0 +1,301 @@
// calogTask.c -- calog task library (see calogTask.h). Spawns and manages other calog
// script contexts over the shared handle table; every native is inline, running on the
// calling script's own context thread.
#include "calogTask.h"
#include "calogHandle.h"
#include <pthread.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#define TASK_TYPE_CONTEXT 1u
// Process-wide task registry shared by every runtime that registers the natives; refCount
// is one per registered runtime, so the singleton is freed only when the LAST runtime shuts
// down (never out from under a still-live runtime's captured userData).
typedef struct TaskLibT {
CalogHandleTableT *handles;
int32_t refCount;
} TaskLibT;
// What a task handle owns: the spawned context plus the id of the context that spawned it.
// ONLY the owner may eval or close a task. Because a context is single-threaded, that rules
// out the two ways taskClose's pthread_join could misbehave: a task can never own its own
// handle (so it can't self-join and free itself mid-run), and two tasks can never each own
// the other's handle (so they can't dead-lock closing each other).
typedef struct TaskT {
CalogContextT *context;
uint64_t ownerId;
} TaskT;
// Maps an engine name to its vtable, for the engines compiled in. References the extern
// vtables only under their CALOG_WITH_* guard, so unselected engines stay unlinked.
typedef struct TaskEngineT {
const char *name;
const CalogEngineT *engine;
} TaskEngineT;
static const TaskEngineT gTaskEngines[] = {
#ifdef CALOG_WITH_LUA
{ "lua", &calogLuaEngine },
#endif
#ifdef CALOG_WITH_JS
{ "js", &calogJsEngine },
#endif
#ifdef CALOG_WITH_SQUIRREL
{ "squirrel", &calogSquirrelEngine },
#endif
#ifdef CALOG_WITH_MYBASIC
{ "mybasic", &calogMyBasicEngine },
#endif
#ifdef CALOG_WITH_BERRY
{ "berry", &calogBerryEngine },
#endif
#ifdef CALOG_WITH_S7
{ "s7", &calogS7Engine },
#endif
#ifdef CALOG_WITH_WREN
{ "wren", &calogWrenEngine },
#endif
{ NULL, NULL }
};
static pthread_mutex_t gTaskLibMutex = PTHREAD_MUTEX_INITIALIZER;
static TaskLibT *gTaskLib = NULL;
static int32_t taskClose(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static void taskCloser(uint32_t type, void *resource);
static int32_t taskCount(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static const CalogEngineT *taskEngineByName(const char *name);
static int32_t taskEval(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t taskLoad(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t taskSelf(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t taskSpawn(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
int32_t calogTaskRegister(CalogT *calog) {
pthread_mutex_lock(&gTaskLibMutex);
if (gTaskLib == NULL) {
TaskLibT *lib;
lib = (TaskLibT *)calloc(1, sizeof(*lib));
if (lib == NULL) {
pthread_mutex_unlock(&gTaskLibMutex);
return calogErrOomE;
}
lib->handles = calogHandleTableCreate();
if (lib->handles == NULL) {
free(lib);
pthread_mutex_unlock(&gTaskLibMutex);
return calogErrOomE;
}
gTaskLib = lib;
}
gTaskLib->refCount++;
pthread_mutex_unlock(&gTaskLibMutex);
calogRegisterInline(calog, "taskSpawn", taskSpawn, gTaskLib);
calogRegisterInline(calog, "taskLoad", taskLoad, gTaskLib);
calogRegisterInline(calog, "taskEval", taskEval, gTaskLib);
calogRegisterInline(calog, "taskClose", taskClose, gTaskLib);
calogRegisterInline(calog, "taskSelf", taskSelf, gTaskLib);
calogRegisterInline(calog, "taskCount", taskCount, gTaskLib);
return calogOkE;
}
void calogTaskShutdown(void) {
pthread_mutex_lock(&gTaskLibMutex);
if (gTaskLib == NULL) {
pthread_mutex_unlock(&gTaskLibMutex);
return;
}
gTaskLib->refCount--;
if (gTaskLib->refCount <= 0) {
// Last runtime is gone. Free the per-task wrappers; the contexts themselves are
// owned by their runtime and were closed by calogDestroy.
calogHandleTableDestroy(gTaskLib->handles, taskCloser);
free(gTaskLib);
gTaskLib = NULL;
}
pthread_mutex_unlock(&gTaskLibMutex);
}
static int32_t taskClose(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
TaskLibT *lib;
TaskT *task;
lib = (TaskLibT *)userData;
calogValueNil(result);
if (argCount != 1 || args[0].type != calogIntE) {
return calogFail(result, calogErrArgE, "taskClose expects (handle)");
}
// Only the owner may close (see TaskT). This check makes a self-join or a mutual close
// unreachable, and because the owner is a single thread it also serialises the peek
// below with the remove -- no other thread can claim this handle.
task = (TaskT *)calogHandleGet(lib->handles, args[0].as.i, TASK_TYPE_CONTEXT);
if (task == NULL) {
return calogFail(result, calogErrArgE, "taskClose: invalid task handle");
}
if (task->ownerId != calogCurrentId()) {
return calogFail(result, calogErrArgE, "taskClose: only the task's owner may close it");
}
task = (TaskT *)calogHandleRemove(lib->handles, args[0].as.i, TASK_TYPE_CONTEXT);
if (task == NULL) {
return calogFail(result, calogErrArgE, "taskClose: invalid task handle");
}
calogContextClose(task->context);
free(task);
return calogOkE;
}
static void taskCloser(uint32_t type, void *resource) {
(void)type;
// Free only the wrapper; the context is owned by its runtime (closed by calogDestroy).
free(resource);
}
static int32_t taskCount(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
TaskLibT *lib;
(void)args;
(void)argCount;
lib = (TaskLibT *)userData;
calogValueInt(result, (int64_t)calogHandleCount(lib->handles, TASK_TYPE_CONTEXT));
return calogOkE;
}
static const CalogEngineT *taskEngineByName(const char *name) {
int32_t index;
for (index = 0; gTaskEngines[index].name != NULL; index++) {
if (strcmp(gTaskEngines[index].name, name) == 0) {
return gTaskEngines[index].engine;
}
}
return NULL;
}
static int32_t taskEval(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
TaskLibT *lib;
TaskT *task;
lib = (TaskLibT *)userData;
calogValueNil(result);
if (argCount != 2 || args[0].type != calogIntE || args[1].type != calogStringE) {
return calogFail(result, calogErrArgE, "taskEval expects (handle, code)");
}
task = (TaskT *)calogHandleGet(lib->handles, args[0].as.i, TASK_TYPE_CONTEXT);
if (task == NULL) {
return calogFail(result, calogErrArgE, "taskEval: invalid task handle");
}
if (task->ownerId != calogCurrentId()) {
return calogFail(result, calogErrArgE, "taskEval: only the task's owner may control it");
}
if (calogContextEval(task->context, args[1].as.s.bytes) != calogOkE) {
return calogFail(result, calogErrArgE, "taskEval: could not queue the code");
}
return calogOkE;
}
static int32_t taskLoad(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
TaskLibT *lib;
CalogT *calog;
CalogContextT *context;
TaskT *task;
int64_t handle;
lib = (TaskLibT *)userData;
calogValueNil(result);
if (argCount != 1 || args[0].type != calogStringE) {
return calogFail(result, calogErrArgE, "taskLoad expects (baseName)");
}
calog = calogCurrent();
if (calog == NULL) {
return calogFail(result, calogErrArgE, "taskLoad: must be called from a script");
}
context = calogContextLoad(calog, args[0].as.s.bytes);
if (context == NULL) {
return calogFail(result, calogErrArgE, "taskLoad: no matching script file, or the load failed");
}
task = (TaskT *)malloc(sizeof(*task));
if (task == NULL) {
calogContextClose(context);
return calogFail(result, calogErrOomE, "taskLoad: out of memory");
}
task->context = context;
task->ownerId = calogCurrentId();
handle = calogHandleAdd(lib->handles, TASK_TYPE_CONTEXT, task);
if (handle == 0) {
free(task);
calogContextClose(context);
return calogFail(result, calogErrOomE, "taskLoad: out of memory");
}
calogValueInt(result, handle);
return calogOkE;
}
static int32_t taskSelf(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
(void)args;
(void)argCount;
(void)userData;
calogValueInt(result, (int64_t)calogCurrentId());
return calogOkE;
}
static int32_t taskSpawn(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
TaskLibT *lib;
CalogT *calog;
const CalogEngineT *engine;
CalogContextT *context;
TaskT *task;
int64_t handle;
lib = (TaskLibT *)userData;
calogValueNil(result);
if (argCount != 2 || args[0].type != calogStringE || args[1].type != calogStringE) {
return calogFail(result, calogErrArgE, "taskSpawn expects (engine, code)");
}
engine = taskEngineByName(args[0].as.s.bytes);
if (engine == NULL) {
return calogFail(result, calogErrUnsupportedE, "taskSpawn: unknown or uncompiled engine");
}
calog = calogCurrent();
if (calog == NULL) {
return calogFail(result, calogErrArgE, "taskSpawn: must be called from a script");
}
context = calogContextOpen(calog, engine);
if (context == NULL) {
return calogFail(result, calogErrArgE, "taskSpawn: could not open a context");
}
task = (TaskT *)malloc(sizeof(*task));
if (task == NULL) {
calogContextClose(context);
return calogFail(result, calogErrOomE, "taskSpawn: out of memory");
}
task->context = context;
task->ownerId = calogCurrentId();
handle = calogHandleAdd(lib->handles, TASK_TYPE_CONTEXT, task);
if (handle == 0) {
free(task);
calogContextClose(context);
return calogFail(result, calogErrOomE, "taskSpawn: out of memory");
}
if (calogContextEval(context, args[1].as.s.bytes) != calogOkE) {
calogHandleRemove(lib->handles, handle, TASK_TYPE_CONTEXT);
free(task);
calogContextClose(context);
return calogFail(result, calogErrArgE, "taskSpawn: could not queue the code");
}
calogValueInt(result, handle);
return calogOkE;
}

45
libs/calogTask.h Normal file
View file

@ -0,0 +1,45 @@
// calogTask.h -- calog task library: launch and manage other calog script contexts.
//
// Registers inline natives that let a script of any engine spawn and manage other scripts:
// taskSpawn(engine, code) -> handle run a code string on a named engine (fire-and-forget)
// taskLoad(baseName) -> handle launch a script FILE (engine chosen by extension)
// taskEval(handle, code) feed more code into a running task (runs on its thread)
// taskClose(handle) stop a task (cooperative shutdown; see below)
// taskSelf() -> id the calling script's own context id
// taskCount() -> n number of tasks this library currently holds open
//
// Tasks are FIRE-AND-FORGET: a spawned context runs on its own thread and returns nothing to
// the caller; results come back through host natives you register (calog's usual pattern). A
// task is a persistent interpreter -- taskEval feeds it more code over time until taskClose.
//
// OWNERSHIP: a task is owned by the context that spawned/loaded it, and ONLY that owner may
// taskEval or taskClose it (others get an error). This is enforced, not just documented: it
// makes taskClose -- which blocks joining the task's thread -- unable to self-join (a task
// cannot hold its own handle) or dead-lock a mutual close. A task whose owner is torn down
// without closing it becomes an orphan, reclaimed when the runtime is destroyed.
//
// taskClose is COOPERATIVE (it is the "kill"): it queues a shutdown and waits for the task's
// thread to exit. A task blocked calling back into the host (a host-thread native) has that
// call interrupted; a task busy in a pure computation is not force-cancelled (that would
// corrupt interpreter state), so a task spinning in an infinite loop cannot be force-killed.
// (A task that, during its shutdown, synchronously invokes a callable owned by the closing
// context can still dead-lock, since the closer is blocked in the join -- avoid that.)
// Engines are addressed by name for
// those compiled in (CALOG_WITH_LUA / _JS / _SQUIRREL / _MYBASIC / _BERRY / _S7 / _WREN);
// taskLoad additionally needs the engines registered with calogRegisterEngine at setup.
#ifndef CALOG_TASK_H
#define CALOG_TASK_H
#include "calog.h"
// Register the task natives on a runtime. Idempotent across runtimes (they share a
// process-wide task registry; each spawn goes into the caller's own runtime). Returns
// calogOkE or an error.
int32_t calogTaskRegister(CalogT *calog);
// Free the process-wide task registry. Call it AFTER the runtime is torn down
// (calogDestroy), which is what actually closes any still-open task contexts.
void calogTaskShutdown(void);
#endif

View file

@ -10,6 +10,10 @@
#include <pthread.h>
// The host context's id (the thread that owns the runtime). A callable owned by the host
// (ownerCtxId == CALOG_HOST_ID) has no separate interpreter to outlive.
#define CALOG_HOST_ID 0
// A registry entry, resolved by name. runInline true means the native runs on the
// calling thread (calogRegisterInline); false means it runs on the host thread.
struct CalogEntryT {
@ -31,6 +35,11 @@ typedef struct CalogRegistrySlotT {
// Invoked when a CalogFnT's last reference drops, so the owning engine can release
// its closure. The broker frees the CalogFnT shell after this returns; reach the
// closure handle with calogFnUserData.
//
// CONTRACT: the userData passed to calogFnCreate must be a SINGLE heap allocation, and
// this hook's only cleanup (beyond the interpreter op) must be free(userData). When the
// owning context is gone, calogFnFinalize skips this hook and frees userData directly --
// the interpreter (and the closure handle in it) is already destroyed.
typedef void (*CalogReleaseFnT)(CalogFnT *fn);
// Hooks the actor layer installs on the runtime (calogActorInit stores them in CalogT)
@ -97,5 +106,6 @@ int32_t calogActorInit(CalogT *calog);
void calogActorShutdown(CalogT *calog);
CalogT *calogContextBroker(const CalogContextT *context);
void *calogContextInterp(CalogContextT *context);
bool calogContextRegistered(CalogT *runtime, uint64_t ctxId);
#endif

View file

@ -41,7 +41,7 @@
// The host context id (script contexts get 1..N). currentContext == calog->hostContext
// means "on this runtime's host thread."
#define CALOG_HOST_ID 0
// CALOG_HOST_ID is defined in calogInternal.h (shared with value.c's finalize path).
// A script context id packs a 1-based slot index in the low CONTEXT_INDEX_BITS and a
// generation counter above it. When a slot is recycled its generation is bumped, so a
@ -98,6 +98,7 @@ struct CalogContextT {
uint64_t nextToken;
bool shuttingDown;
bool started;
bool interpDead; // set (under ctxMutex) once the interpreter is torn down
};
// currentContext is the ONLY process-global actor state -- and it is thread-local: it
@ -114,6 +115,7 @@ static void contextDispatchCall(CalogContextT *context, MessageT *mes
static void contextDispatchError(CalogT *calog, MessageT *message);
static void contextDispatchEval(CalogContextT *context, MessageT *message);
static void contextDispatchRelease(MessageT *message);
static void contextDrainQueue(CalogContextT *context);
static int32_t contextEnqueue(CalogT *calog, uint64_t targetId, MessageT *message);
static int32_t contextPostRelease(CalogT *calog, uint64_t targetId, CalogFnT *callable);
static void contextReply(CalogT *calog, MessageT *message, int32_t status, CalogValueT *result);
@ -228,19 +230,32 @@ void calogActorShutdown(CalogT *calog) {
enqueueRaw(context, message);
}
}
// Join EVERY thread before freeing ANY context: a context tearing down may release a
// callable owned by a sibling (marshalled across contexts), which resolves/posts to that
// sibling -- so no sibling may be freed while another's thread still runs.
for (index = 0; index < calog->ctxCount; index++) {
CalogContextT *context;
context = calog->ctxSlots[index].context;
if (context != NULL && context->started) {
pthread_join(context->thread, NULL);
}
}
// All context threads are stopped. Unregister each under ctxMutex (so any in-flight
// registryResolveLocked from the host sees NULL rather than a freed slot), drain any
// orphaned release, then free.
for (index = 0; index < calog->ctxCount; index++) {
CalogContextT *context;
context = calog->ctxSlots[index].context;
if (context == NULL) {
continue;
}
if (context->started) {
pthread_join(context->thread, NULL);
}
pthread_mutex_lock(&calog->ctxMutex);
calog->ctxSlots[index].context = NULL;
pthread_mutex_unlock(&calog->ctxMutex);
contextDrainQueue(context);
pthread_mutex_destroy(&context->queueMutex);
pthread_cond_destroy(&context->queueCond);
free(context);
calog->ctxSlots[index].context = NULL;
}
free(calog->ctxSlots);
free(calog->ctxFree);
@ -482,6 +497,7 @@ void calogContextClose(CalogContextT *context) {
registryFreePush(broker, index);
}
pthread_mutex_unlock(&broker->ctxMutex);
contextDrainQueue(context);
pthread_mutex_destroy(&context->queueMutex);
pthread_cond_destroy(&context->queueCond);
free(context);
@ -589,6 +605,24 @@ static void contextDispatchRelease(MessageT *message) {
}
static void contextDrainQueue(CalogContextT *context) {
MessageT *message;
// Called at teardown once the owning thread has stopped and the context is unregistered,
// so no new messages can arrive. A release can be orphaned here if a last drop of one of
// this context's callables raced its shutdown (enqueued after serveLoop stopped serving);
// finalize those so the callable is not leaked, and free every other pending message.
while ((message = tryDequeue(context)) != NULL) {
if (message->kind == messageReleaseE) {
calogFnFinalize(message->callable);
free(message);
} else {
messageFree(message);
}
}
}
static int32_t contextEnqueue(CalogT *calog, uint64_t targetId, MessageT *message) {
CalogContextT *target;
int64_t index;
@ -669,6 +703,19 @@ void *calogContextInterp(CalogContextT *context) {
}
bool calogContextRegistered(CalogT *runtime, uint64_t ctxId) {
bool registered;
if (runtime == NULL) {
return false;
}
pthread_mutex_lock(&runtime->ctxMutex);
registered = (registryResolveLocked(runtime, ctxId) != NULL);
pthread_mutex_unlock(&runtime->ctxMutex);
return registered;
}
void calogPump(CalogT *calog) {
CalogContextT *previous;
MessageT *message;
@ -1019,6 +1066,11 @@ static CalogContextT *registryResolveLocked(CalogT *calog, uint64_t id) {
if (calog->ctxSlots[index].generation != idGeneration(id)) {
return NULL;
}
// Interpreter already torn down: treat as gone so late releases finalize without touching
// it (the slot itself stays populated until calogContextClose/calogActorShutdown frees it).
if (calog->ctxSlots[index].context->interpDead) {
return NULL;
}
return calog->ctxSlots[index].context;
}
@ -1080,6 +1132,13 @@ static void *threadMain(void *arg) {
context->engine->createInterpreter(context, &context->interp);
}
serveLoop(context);
// Mark the interpreter dead BEFORE destroying it, so registryResolveLocked stops handing
// this context out: a callable this context owns that is released from now on (e.g. one
// published via the export library and dropped after the context unloads) finalizes by
// freeing its struct directly instead of running the engine release on a dead interpreter.
pthread_mutex_lock(&context->broker->ctxMutex);
context->interpDead = true;
pthread_mutex_unlock(&context->broker->ctxMutex);
if (context->engine != NULL && context->engine->destroyInterpreter != NULL) {
context->engine->destroyInterpreter(context->interp);
}

View file

@ -38,6 +38,7 @@ struct CalogJsT {
CalogT *broker;
uint64_t ctxId;
JSClassID fnClassId; // class for a foreign CalogFnT pushed into JS (callable + finalized)
JSClassID resolverClassId; // class for the exotic prototype that resolves bare export names
};
// Backs a CalogFnT exported from this context: the retained JS function value (kept
@ -53,9 +54,14 @@ static int32_t jsExportValue(CalogJsT *context, JSValueConst fn, CalogFnT **out)
static JSValue jsForeignCall(JSContext *ctx, JSValueConst funcObj, JSValueConst thisVal, int argc, JSValueConst *argv, int flags);
static void jsForeignFinalize(JSRuntime *rt, JSValueConst val);
static JSValue jsFromValue(JSContext *ctx, const CalogValueT *value, int32_t depth);
static int jsResolveOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, JSValueConst obj, JSAtom prop);
static int32_t jsToValue(JSContext *ctx, JSValueConst val, CalogValueT *out, int32_t depth);
static JSValue jsTrampoline(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic, JSValueConst *func_data);
// Exotic behavior for the resolver prototype: an unknown global read consults the export
// registry. get_own_property alone suffices -- QuickJS derives has/get from it.
static JSClassExoticMethods jsResolverExotic = { .get_own_property = jsResolveOwnProperty };
int32_t calogJsCreate(CalogJsT **out, CalogT *broker, uint64_t ctxId) {
CalogJsT *context;
@ -92,6 +98,31 @@ int32_t calogJsCreate(CalogJsT **out, CalogT *broker, uint64_t ctxId) {
def.exotic = NULL;
JS_NewClass(context->rt, context->fnClassId, &def);
}
// Bare-name export resolution: insert an exotic object into the global object's prototype
// chain (keeping the original prototype below it) so a read of an otherwise-undefined
// global consults the export registry via jsResolveOwnProperty.
JS_NewClassID(context->rt, &context->resolverClassId);
{
JSClassDef def;
def.class_name = "CalogResolver";
def.finalizer = NULL;
def.gc_mark = NULL;
def.call = NULL;
def.exotic = &jsResolverExotic;
JS_NewClass(context->rt, context->resolverClassId, &def);
}
{
JSValue global;
JSValue originalProto;
JSValue resolverProto;
global = JS_GetGlobalObject(context->ctx);
originalProto = JS_GetPrototype(context->ctx, global);
resolverProto = JS_NewObjectProtoClass(context->ctx, originalProto, context->resolverClassId);
JS_SetPrototype(context->ctx, global, resolverProto);
JS_FreeValue(context->ctx, resolverProto);
JS_FreeValue(context->ctx, originalProto);
JS_FreeValue(context->ctx, global);
}
*out = context;
return calogOkE;
}
@ -422,6 +453,47 @@ int32_t calogJsRun(CalogJsT *context, const char *source) {
}
static int jsResolveOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, JSValueConst obj, JSAtom prop) {
CalogJsT *context;
CalogValueT nameArg;
CalogValueT result;
const char *name;
size_t nameLen;
int32_t status;
(void)obj;
context = (CalogJsT *)JS_GetContextOpaque(ctx);
name = JS_AtomToCStringLen(ctx, &nameLen, prop);
if (name == NULL) {
return 0;
}
status = calogValueString(&nameArg, name, (int64_t)nameLen);
JS_FreeCString(ctx, name);
if (status != calogOkE) {
return 0;
}
calogValueNil(&result);
status = calogCall(context->broker, "__exportResolve", &nameArg, 1, &result);
calogValueFree(&nameArg);
if (status != calogOkE || result.type != calogFnE) {
calogValueFree(&result);
return 0; // not exported -> fall through the prototype chain / ReferenceError
}
// Existence probe (desc == NULL) must not marshal, or the reference would leak.
if (desc != NULL) {
// Writable so a script can still shadow the export with its own global: assigning to
// the name creates an own property on globalThis rather than hitting this read-only
// prototype slot (which would silently drop the write / throw in strict mode).
desc->flags = JS_PROP_C_W_E;
desc->value = jsFromValue(ctx, &result, 0);
desc->getter = JS_UNDEFINED;
desc->setter = JS_UNDEFINED;
}
calogValueFree(&result);
return 1;
}
static int32_t jsToValue(JSContext *ctx, JSValueConst val, CalogValueT *out, int32_t depth) {
calogValueNil(out);
if (depth > CALOG_MAX_DEPTH) {

View file

@ -52,6 +52,7 @@ static CalogLuaT *luaContextOf(lua_State *L);
static int32_t luaExportAt(CalogLuaT *context, int idx, CalogFnT **out);
static int luaFunctionCall(lua_State *L);
static int luaFunctionGc(lua_State *L);
static int luaGlobalResolve(lua_State *L);
static int32_t luaPushValueDepth(lua_State *L, const CalogValueT *value, int32_t depth);
static int32_t luaToValueDepth(lua_State *L, int idx, CalogValueT *out, int32_t depth);
static int luaTrampoline(lua_State *L);
@ -130,6 +131,17 @@ int32_t calogLuaCreate(CalogLuaT **out, CalogT *broker, uint64_t ctxId) {
lua_setfield(L, -2, "__gc");
lua_pop(L, 1);
// Give the globals table an __index that resolves an unknown name through the export
// registry (if the export library is registered), so a function published with
// export(name, fn) is callable by its bare name. A name that is neither a real global nor
// an export resolves to nil, exactly as before.
lua_pushglobaltable(L);
lua_newtable(L);
lua_pushcfunction(L, luaGlobalResolve);
lua_setfield(L, -2, "__index");
lua_setmetatable(L, -2);
lua_pop(L, 1);
*out = context;
return calogOkE;
}
@ -304,6 +316,42 @@ static int luaFunctionGc(lua_State *L) {
}
// __index on the globals table: resolve an unknown name through the export registry. Returns
// the exported function as a callable, or nil (unknown name behaves exactly as before). The
// __exportResolve native is a no-op returning nil if the export library is not registered.
static int luaGlobalResolve(lua_State *L) {
CalogLuaT *context;
CalogValueT nameArg;
CalogValueT result;
const char *name;
size_t nameLength;
int32_t status;
if (lua_type(L, 2) != LUA_TSTRING) {
lua_pushnil(L);
return 1;
}
name = lua_tolstring(L, 2, &nameLength);
context = luaContextOf(L);
if (calogValueString(&nameArg, name, (int64_t)nameLength) != calogOkE) {
lua_pushnil(L);
return 1;
}
calogValueNil(&result);
status = calogCall(context->broker, "__exportResolve", &nameArg, 1, &result);
calogValueFree(&nameArg);
if (status == calogOkE && result.type == calogFnE) {
if (luaPushValueDepth(L, &result, 0) != calogOkE) {
lua_pushnil(L);
}
} else {
lua_pushnil(L);
}
calogValueFree(&result);
return 1;
}
static int32_t luaPushValueDepth(lua_State *L, const CalogValueT *value, int32_t depth) {
int32_t status;
int64_t index;

View file

@ -54,6 +54,7 @@ static int32_t s7ExportValue(CalogS7T *context, s7_pointer proc, CalogFnT **
static s7_pointer s7ForeignApply(s7_scheme *sc, s7_pointer args);
static void s7ForeignFree(void *value);
static s7_pointer s7FromValue(CalogS7T *context, const CalogValueT *value, int32_t depth);
static s7_pointer s7ResolveUnbound(s7_scheme *sc, s7_pointer args);
static int32_t s7ToValue(CalogS7T *context, s7_pointer obj, CalogValueT *out, int32_t depth);
@ -81,6 +82,14 @@ int32_t calogS7Create(CalogS7T **out, CalogT *broker, uint64_t ctxId) {
context->fnType = s7_make_c_type(context->sc, "calog-fn");
s7_c_type_set_ref(context->sc, context->fnType, s7ForeignApply);
s7_c_type_set_free(context->sc, context->fnType, s7ForeignFree);
// Bare-name export resolution: when a symbol is unbound, *unbound-variable-hook* fires;
// s7ResolveUnbound looks the name up in the export registry and, if found, sets the
// hook's result so (exportedFn args) works without an explicit call().
{
s7_pointer resolver;
resolver = s7_make_function(context->sc, "%calog-unbound", s7ResolveUnbound, 1, 0, false, "calog export resolver");
s7_hook_set_functions(context->sc, s7_name_to_value(context->sc, "*unbound-variable-hook*"), s7_list(context->sc, 1, resolver));
}
*out = context;
return calogOkE;
}
@ -445,6 +454,37 @@ int32_t calogS7Run(CalogS7T *context, const char *source) {
}
static s7_pointer s7ResolveUnbound(s7_scheme *sc, s7_pointer args) {
CalogS7T *context;
CalogValueT nameArg;
CalogValueT result;
s7_pointer hookLet;
s7_pointer sym;
const char *name;
int32_t status;
// The hook passes its let; 'variable holds the unbound symbol, 'result is what we set.
hookLet = s7_car(args);
sym = s7_let_ref(sc, hookLet, s7_make_symbol(sc, "variable"));
if (!s7_is_symbol(sym)) {
return s7_unspecified(sc);
}
name = s7_symbol_name(sym);
context = (CalogS7T *)s7_c_pointer(s7_name_to_value(sc, S7_CONTEXT_VAR));
if (calogValueString(&nameArg, name, (int64_t)strlen(name)) != calogOkE) {
return s7_unspecified(sc);
}
calogValueNil(&result);
status = calogCall(context->broker, "__exportResolve", &nameArg, 1, &result);
calogValueFree(&nameArg);
if (status == calogOkE && result.type == calogFnE) {
s7_let_set(sc, hookLet, s7_make_symbol(sc, "result"), s7FromValue(context, &result, 0));
}
calogValueFree(&result);
return s7_unspecified(sc);
}
static int32_t s7ToValue(CalogS7T *context, s7_pointer obj, CalogValueT *out, int32_t depth) {
s7_scheme *sc;

View file

@ -56,6 +56,7 @@ static SQInteger squirrelForeignCall(HSQUIRRELVM v);
static SQInteger squirrelForeignRelease(SQUserPointer p, SQInteger size);
static void squirrelPrint(HSQUIRRELVM v, const SQChar *format, ...);
static int32_t squirrelPushValueDepth(HSQUIRRELVM v, const CalogValueT *value, int32_t depth);
static SQInteger squirrelResolveGet(HSQUIRRELVM v);
static int32_t squirrelToValueDepth(HSQUIRRELVM v, SQInteger idx, CalogValueT *out, int32_t depth);
static SQInteger squirrelTrampoline(HSQUIRRELVM v);
@ -121,6 +122,16 @@ int32_t calogSquirrelCreate(CalogSquirrelT **out, CalogT *broker, uint64_t ctxId
context->ctxId = ctxId;
sq_setforeignptr(v, context);
sq_setprintfunc(v, squirrelPrint, squirrelPrint);
// Install a root-table delegate whose _get resolves a missing name against the export
// registry, so an exported function is callable by its bare name. Native slots are own
// slots of the root table, so _get fires only for names the root does not already have.
sq_pushroottable(v);
sq_newtable(v);
sq_pushstring(v, _SC("_get"), -1);
sq_newclosure(v, squirrelResolveGet, 0);
sq_newslot(v, -3, SQFalse);
sq_setdelegate(v, -2);
sq_pop(v, 1);
*out = context;
return calogOkE;
}
@ -458,6 +469,38 @@ int32_t calogSquirrelRun(CalogSquirrelT *context, const char *source) {
}
static SQInteger squirrelResolveGet(HSQUIRRELVM v) {
CalogSquirrelT *context;
CalogValueT nameArg;
CalogValueT result;
const SQChar *key;
int32_t status;
// _get(key): 'this' (the root table) is at index 1, the missing key at index 2.
if (SQ_FAILED(sq_getstring(v, 2, &key))) {
return sq_throwerror(v, _SC("calog resolver: non-string index"));
}
context = squirrelContextOf(v);
if (calogValueString(&nameArg, key, (int64_t)strlen(key)) != calogOkE) {
return sq_throwerror(v, _SC("calog resolver: out of memory"));
}
calogValueNil(&result);
status = calogCall(context->broker, "__exportResolve", &nameArg, 1, &result);
calogValueFree(&nameArg);
if (status == calogOkE && result.type == calogFnE) {
status = squirrelPushValueDepth(v, &result, 0);
calogValueFree(&result);
if (status != calogOkE) {
return sq_throwerror(v, _SC("calog resolver: failed to marshal export"));
}
return 1;
}
calogValueFree(&result);
// Not exported: raise the normal missing-index error.
return sq_throwerror(v, _SC("the index does not exist"));
}
static int32_t squirrelToValueDepth(HSQUIRRELVM v, SQInteger idx, CalogValueT *out, int32_t depth) {
SQObjectType type;
SQInteger absIdx;

View file

@ -206,12 +206,22 @@ void calogFnFinalize(CalogFnT *callable) {
if (callable == NULL) {
return;
}
// Last reference is gone: run the engine's closure release (which also frees the
// engine's per-callable struct), then free the shell. The actor layer guarantees
// this runs on the owner's thread (design.md sec 10), so the interpreter op is
// safe; in the core (no actor) it runs inline.
// Last reference is gone. If the owner context is still alive, run the engine's closure
// release (luaL_unref / sq_release / ...), which also frees the engine's per-callable
// struct; the actor layer routes this to the owner's thread (design.md sec 10) so the
// interpreter op is safe. If the owner is GONE, its interpreter -- and this callable's
// handle inside it -- were already destroyed, so we must NOT touch it: free the engine's
// per-callable struct directly. This is what lets an exported function outlive its
// context (e.g. a script unloaded and reloaded, re-exporting new versions).
//
// (Freeing userData directly requires every engine's per-callable struct to be a single
// heap allocation; all adapters honor that -- see CalogReleaseFnT in calogInternal.h.)
if (callable->release != NULL) {
if (callable->ownerCtxId == CALOG_HOST_ID || calogContextRegistered(callable->runtime, callable->ownerCtxId)) {
callable->release(callable);
} else {
free(callable->userData);
}
}
free(callable);
}

225
tests/testDb.c Normal file
View file

@ -0,0 +1,225 @@
// testDb.c -- exercises the calog DB library end to end against an in-memory SQLite
// database, driven from a Lua script: open, create, insert with bound params (including
// binary-safe data), update (rows-affected), query into row maps, close, and an error path.
#define _POSIX_C_SOURCE 200809L
#include "calog.h"
#include "calogDb.h"
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define CHECK(cond, msg) checkImpl((cond), (msg), __FILE__, __LINE__)
#define PUMP_LIMIT 4000
static CalogT *calog = NULL;
static _Atomic int64_t reportedCount = -1;
static _Atomic int64_t reportedId = -1;
static _Atomic int64_t execAffected = -1;
static char reportedName[32] = { 0 };
static char blobData[32] = { 0 };
static _Atomic int32_t blobLen = -1;
static _Atomic bool scriptDone = false;
static _Atomic int32_t errorCount = 0;
static int32_t testsRun = 0;
static int32_t testsFailed = 0;
static void checkImpl(bool condition, const char *message, const char *file, int32_t line);
static int32_t nativeDone(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t nativeReport(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t nativeReportBlob(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static void onError(uint64_t contextId, const char *message, void *userData);
static void pumpUntilDone(void);
static void testDbBinary(void);
static void testDbError(void);
static void testDbRoundtrip(void);
static void checkImpl(bool condition, const char *message, const char *file, int32_t line) {
testsRun++;
if (!condition) {
testsFailed++;
printf("FAIL %s:%d %s\n", file, line, message);
}
}
static int32_t nativeDone(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
(void)args;
(void)argCount;
(void)userData;
atomic_store(&scriptDone, true);
calogValueNil(result);
return calogOkE;
}
static int32_t nativeReport(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
size_t length;
(void)userData;
calogValueNil(result);
if (argCount != 4 || args[0].type != calogIntE || args[1].type != calogIntE || args[2].type != calogStringE || args[3].type != calogIntE) {
return calogFail(result, calogErrArgE, "report expects (count, id, name, affected)");
}
atomic_store(&reportedCount, args[0].as.i);
atomic_store(&reportedId, args[1].as.i);
length = (size_t)args[2].as.s.length;
if (length >= sizeof(reportedName)) {
length = sizeof(reportedName) - 1;
}
memcpy(reportedName, args[2].as.s.bytes, length);
reportedName[length] = '\0';
atomic_store(&execAffected, args[3].as.i);
return calogOkE;
}
static int32_t nativeReportBlob(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
size_t length;
(void)userData;
calogValueNil(result);
if (argCount != 1 || args[0].type != calogStringE) {
return calogFail(result, calogErrArgE, "reportBlob expects one string");
}
length = (size_t)args[0].as.s.length;
if (length > sizeof(blobData)) {
length = sizeof(blobData);
}
memcpy(blobData, args[0].as.s.bytes, length);
atomic_store(&blobLen, (int32_t)length);
return calogOkE;
}
static void onError(uint64_t contextId, const char *message, void *userData) {
(void)contextId;
(void)message;
(void)userData;
atomic_fetch_add(&errorCount, 1);
}
static void pumpUntilDone(void) {
struct timespec ts = { 0, 500000 };
int errorsBefore;
int i;
errorsBefore = atomic_load(&errorCount);
for (i = 0; i < PUMP_LIMIT; i++) {
calogPump(calog);
if (atomic_load(&scriptDone) || atomic_load(&errorCount) != errorsBefore) {
calogPump(calog);
return;
}
nanosleep(&ts, NULL);
}
}
static void testDbBinary(void) {
CalogContextT *ctx;
ctx = calogContextOpen(calog, &calogLuaEngine);
atomic_store(&scriptDone, false);
atomic_store(&blobLen, -1);
// Bind and read back a value with an embedded NUL -- proves binary-safe round-trip.
calogContextEval(ctx,
"local db = dbOpen('sqlite', ':memory:')\n"
"dbExec(db, 'create table b (v blob)')\n"
"dbExec(db, 'insert into b values (?)', 'a\\0b')\n"
"local rows = dbQuery(db, 'select v from b')\n"
"reportBlob(rows[1].v)\n"
"dbClose(db)\n"
"done()");
pumpUntilDone();
CHECK(atomic_load(&blobLen) == 3, "binary value round-tripped with its exact byte length");
CHECK(blobData[0] == 'a' && blobData[1] == '\0' && blobData[2] == 'b', "the embedded NUL survived the DB round-trip");
calogContextClose(ctx);
}
static void testDbError(void) {
CalogContextT *ctx;
int32_t before;
ctx = calogContextOpen(calog, &calogLuaEngine);
before = atomic_load(&errorCount);
atomic_store(&scriptDone, false);
// Invalid SQL should surface as a script-level error (the native fails).
calogContextEval(ctx,
"local db = dbOpen('sqlite', ':memory:')\n"
"dbQuery(db, 'select * from nonexistent_table')\n"
"done()");
pumpUntilDone();
CHECK(atomic_load(&errorCount) == before + 1, "a bad query raised a script-level error");
calogContextClose(ctx);
}
static void testDbRoundtrip(void) {
CalogContextT *ctx;
ctx = calogContextOpen(calog, &calogLuaEngine);
atomic_store(&scriptDone, false);
atomic_store(&reportedCount, -1);
calogContextEval(ctx,
"local db = dbOpen('sqlite', ':memory:')\n"
"dbExec(db, 'create table t (id integer, name text)')\n"
"dbExec(db, 'insert into t values (?, ?)', 1, 'alice')\n"
"dbExec(db, 'insert into t values (?, ?)', 2, 'bob')\n"
"local n = dbExec(db, 'update t set name = ? where id = ?', 'bobby', 2)\n"
"local rows = dbQuery(db, 'select id, name from t order by id')\n"
"report(#rows, rows[2].id, rows[2].name, n)\n"
"dbClose(db)\n"
"done()");
pumpUntilDone();
CHECK(atomic_load(&reportedCount) == 2, "dbQuery returned both rows");
CHECK(atomic_load(&reportedId) == 2, "the second row's integer column read back correctly");
CHECK(strcmp(reportedName, "bobby") == 0, "a bound-param update took effect and the text column read back");
CHECK(atomic_load(&execAffected) == 1, "dbExec reported the correct rows-affected count");
calogContextClose(ctx);
}
int main(void) {
calog = calogCreate();
if (calog == NULL) {
printf("calog create failed\n");
return 1;
}
calogSetErrorHandler(calog, onError, NULL);
calogRegister(calog, "report", nativeReport, NULL);
calogRegister(calog, "reportBlob", nativeReportBlob, NULL);
calogRegister(calog, "done", nativeDone, NULL);
if (calogDbRegister(calog) != calogOkE) {
printf("calogDbRegister failed\n");
return 1;
}
testDbRoundtrip();
testDbBinary();
testDbError();
calogDestroy(calog);
calogDbShutdown();
printf("\n%d checks, %d failed\n", testsRun, testsFailed);
fflush(stdout);
if (testsFailed != 0) {
return 1;
}
return 0;
}

171
tests/testDbMysql.c Normal file
View file

@ -0,0 +1,171 @@
// testDbMysql.c -- MySQL/MariaDB backend test. Given a "key=value" conninfo on argv[1],
// drives a create/insert/update/query round-trip from a Lua script through the DB library.
// If no server is reachable, dbOpen raises a script error and no row is ever reported; that
// case is treated as SKIP (the clean error path is still exercised), so the test is safe to
// run with or without a live server.
#define _POSIX_C_SOURCE 200809L
#include "calog.h"
#include "calogDb.h"
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define CHECK(cond, msg) checkImpl((cond), (msg), __FILE__, __LINE__)
#define PUMP_LIMIT 4000
static CalogT *calog = NULL;
static _Atomic int64_t reportedCount = -1;
static _Atomic int64_t reportedId = -1;
static _Atomic int64_t execAffected = -1;
static _Atomic int64_t reportedOk = -1;
static char reportedName[32] = { 0 };
static double reportedScore = 0.0;
static _Atomic bool scriptDone = false;
static _Atomic int32_t errorCount = 0;
static int32_t testsRun = 0;
static int32_t testsFailed = 0;
static void checkImpl(bool condition, const char *message, const char *file, int32_t line);
static int32_t nativeDone(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t nativeReport(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static void onError(uint64_t contextId, const char *message, void *userData);
static void pumpUntilDone(void);
static void checkImpl(bool condition, const char *message, const char *file, int32_t line) {
testsRun++;
if (!condition) {
testsFailed++;
printf("FAIL %s:%d %s\n", file, line, message);
}
}
static int32_t nativeDone(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
(void)args;
(void)argCount;
(void)userData;
atomic_store(&scriptDone, true);
calogValueNil(result);
return calogOkE;
}
static int32_t nativeReport(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
size_t length;
(void)userData;
calogValueNil(result);
if (argCount != 6 || args[0].type != calogIntE || args[1].type != calogIntE || args[2].type != calogStringE || args[3].type != calogIntE || args[4].type != calogRealE || args[5].type != calogIntE) {
return calogFail(result, calogErrArgE, "report expects (count, id, name, affected, score, ok)");
}
atomic_store(&reportedCount, args[0].as.i);
atomic_store(&reportedId, args[1].as.i);
length = (size_t)args[2].as.s.length;
if (length >= sizeof(reportedName)) {
length = sizeof(reportedName) - 1;
}
memcpy(reportedName, args[2].as.s.bytes, length);
reportedName[length] = '\0';
atomic_store(&execAffected, args[3].as.i);
reportedScore = args[4].as.r;
atomic_store(&reportedOk, args[5].as.i);
return calogOkE;
}
static void onError(uint64_t contextId, const char *message, void *userData) {
(void)contextId;
(void)userData;
fprintf(stderr, " [script error] %s\n", (message != NULL) ? message : "(null)");
atomic_fetch_add(&errorCount, 1);
}
static void pumpUntilDone(void) {
struct timespec ts = { 0, 500000 };
int errorsBefore;
int i;
errorsBefore = atomic_load(&errorCount);
for (i = 0; i < PUMP_LIMIT; i++) {
calogPump(calog);
if (atomic_load(&scriptDone) || atomic_load(&errorCount) != errorsBefore) {
calogPump(calog);
return;
}
nanosleep(&ts, NULL);
}
}
int main(int argc, char **argv) {
CalogContextT *ctx;
char script[2048];
const char *conninfo;
if (argc < 2) {
printf("usage: testDbMysql <conninfo>\n");
return 2;
}
conninfo = argv[1];
calog = calogCreate();
if (calog == NULL) {
printf("calog create failed\n");
return 1;
}
calogSetErrorHandler(calog, onError, NULL);
calogRegister(calog, "report", nativeReport, NULL);
calogRegister(calog, "done", nativeDone, NULL);
if (calogDbRegister(calog) != calogOkE) {
printf("calogDbRegister failed\n");
return 1;
}
snprintf(script, sizeof(script),
"local db = dbOpen('mysql', '%s')\n"
"dbExec(db, 'drop table if exists ct')\n"
"dbExec(db, 'create table ct (id int, name text, score double, ok tinyint)')\n"
"dbExec(db, 'insert into ct values (?, ?, ?, ?)', 1, 'alice', 3.5, true)\n"
"dbExec(db, 'insert into ct values (?, ?, ?, ?)', 2, 'bob', 7.25, false)\n"
"local n = dbExec(db, 'update ct set name = ? where id = ?', 'bobby', 2)\n"
"local rows = dbQuery(db, 'select id, name, score, ok from ct order by id')\n"
"report(#rows, rows[2].id, rows[2].name, n, rows[2].score, rows[2].ok)\n"
"dbClose(db)\n"
"done()",
conninfo);
ctx = calogContextOpen(calog, &calogLuaEngine);
calogContextEval(ctx, script);
pumpUntilDone();
if (atomic_load(&reportedCount) < 0) {
printf("SKIP: no MySQL server reachable (connection error path exercised, no crash)\n");
calogContextClose(ctx);
calogDestroy(calog);
calogDbShutdown();
return 0;
}
CHECK(atomic_load(&reportedCount) == 2, "MySQL dbQuery returned both rows");
CHECK(atomic_load(&reportedId) == 2, "the integer column read back typed");
CHECK(strcmp(reportedName, "bobby") == 0, "a bound-param update took effect; text read back");
CHECK(atomic_load(&execAffected) == 1, "dbExec reported the correct rows-affected");
CHECK(reportedScore == 7.25, "the double column read back as a real");
CHECK(atomic_load(&reportedOk) == 0, "the tinyint(bool) column read back as 0");
calogContextClose(ctx);
calogDestroy(calog);
calogDbShutdown();
printf("\n%d checks, %d failed\n", testsRun, testsFailed);
fflush(stdout);
return (testsFailed != 0) ? 1 : 0;
}

190
tests/testDbPg.c Normal file
View file

@ -0,0 +1,190 @@
// testDbPg.c -- live Postgres backend test. Given a libpq conninfo string on argv[1],
// drives a create/insert/update/query round-trip from a Lua script through the DB library
// and checks the typed values (int, text, double, bool) that come back.
#define _POSIX_C_SOURCE 200809L
#include "calog.h"
#include "calogDb.h"
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define CHECK(cond, msg) checkImpl((cond), (msg), __FILE__, __LINE__)
#define PUMP_LIMIT 4000
static CalogT *calog = NULL;
static _Atomic int64_t reportedCount = -1;
static _Atomic int64_t reportedId = -1;
static _Atomic int64_t execAffected = -1;
static char reportedName[32] = { 0 };
static char reportedBlob[16] = { 0 };
static _Atomic int32_t reportedBlobLen = -1;
static double reportedScore = 0.0;
static _Atomic bool reportedOk = true;
static _Atomic bool scriptDone = false;
static _Atomic int32_t errorCount = 0;
static int32_t testsRun = 0;
static int32_t testsFailed = 0;
static void checkImpl(bool condition, const char *message, const char *file, int32_t line);
static int32_t nativeDone(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t nativeReport(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t nativeReportBlob(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static void onError(uint64_t contextId, const char *message, void *userData);
static void pumpUntilDone(void);
static void checkImpl(bool condition, const char *message, const char *file, int32_t line) {
testsRun++;
if (!condition) {
testsFailed++;
printf("FAIL %s:%d %s\n", file, line, message);
}
}
static int32_t nativeDone(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
(void)args;
(void)argCount;
(void)userData;
atomic_store(&scriptDone, true);
calogValueNil(result);
return calogOkE;
}
static int32_t nativeReport(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
size_t length;
(void)userData;
calogValueNil(result);
if (argCount != 6 || args[0].type != calogIntE || args[1].type != calogIntE || args[2].type != calogStringE || args[3].type != calogIntE || args[4].type != calogRealE || args[5].type != calogBoolE) {
return calogFail(result, calogErrArgE, "report expects (count, id, name, affected, score, ok)");
}
atomic_store(&reportedCount, args[0].as.i);
atomic_store(&reportedId, args[1].as.i);
length = (size_t)args[2].as.s.length;
if (length >= sizeof(reportedName)) {
length = sizeof(reportedName) - 1;
}
memcpy(reportedName, args[2].as.s.bytes, length);
reportedName[length] = '\0';
atomic_store(&execAffected, args[3].as.i);
reportedScore = args[4].as.r;
atomic_store(&reportedOk, args[5].as.b);
return calogOkE;
}
static int32_t nativeReportBlob(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
size_t length;
(void)userData;
calogValueNil(result);
if (argCount != 1 || args[0].type != calogStringE) {
return calogFail(result, calogErrArgE, "reportBlob expects one string");
}
length = (size_t)args[0].as.s.length;
if (length > sizeof(reportedBlob)) {
length = sizeof(reportedBlob);
}
memcpy(reportedBlob, args[0].as.s.bytes, length);
atomic_store(&reportedBlobLen, (int32_t)length);
return calogOkE;
}
static void onError(uint64_t contextId, const char *message, void *userData) {
(void)contextId;
(void)userData;
(void)message;
atomic_fetch_add(&errorCount, 1);
}
static void pumpUntilDone(void) {
struct timespec ts = { 0, 500000 };
int errorsBefore;
int i;
errorsBefore = atomic_load(&errorCount);
for (i = 0; i < PUMP_LIMIT; i++) {
calogPump(calog);
if (atomic_load(&scriptDone) || atomic_load(&errorCount) != errorsBefore) {
calogPump(calog);
return;
}
nanosleep(&ts, NULL);
}
}
int main(int argc, char **argv) {
CalogContextT *ctx;
char script[2048];
const char *conninfo;
if (argc < 2) {
printf("usage: testDbPg <conninfo>\n");
return 2;
}
conninfo = argv[1];
calog = calogCreate();
if (calog == NULL) {
printf("calog create failed\n");
return 1;
}
calogSetErrorHandler(calog, onError, NULL);
calogRegister(calog, "report", nativeReport, NULL);
calogRegister(calog, "reportBlob", nativeReportBlob, NULL);
calogRegister(calog, "done", nativeDone, NULL);
if (calogDbRegister(calog) != calogOkE) {
printf("calogDbRegister failed\n");
return 1;
}
snprintf(script, sizeof(script),
"local db = dbOpen('postgres', '%s')\n"
"dbExec(db, 'drop table if exists ct')\n"
"dbExec(db, 'create table ct (id int, name text, score double precision, ok boolean)')\n"
"dbExec(db, 'insert into ct values ($1, $2, $3, $4)', 1, 'alice', 3.5, true)\n"
"dbExec(db, 'insert into ct values ($1, $2, $3, $4)', 2, 'bob', 7.25, false)\n"
"local n = dbExec(db, 'update ct set name = $1 where id = $2', 'bobby', 2)\n"
"local rows = dbQuery(db, 'select id, name, score, ok from ct order by id')\n"
"report(#rows, rows[2].id, rows[2].name, n, rows[2].score, rows[2].ok)\n"
"dbExec(db, 'drop table if exists bb')\n"
"dbExec(db, 'create table bb (v bytea)')\n"
"dbExec(db, 'insert into bb values ($1)', 'x\\0y')\n"
"local br = dbQuery(db, 'select v from bb')\n"
"reportBlob(br[1].v)\n"
"dbClose(db)\n"
"done()",
conninfo);
ctx = calogContextOpen(calog, &calogLuaEngine);
calogContextEval(ctx, script);
pumpUntilDone();
CHECK(atomic_load(&reportedCount) == 2, "Postgres dbQuery returned both rows");
CHECK(atomic_load(&reportedId) == 2, "the integer column read back typed");
CHECK(strcmp(reportedName, "bobby") == 0, "a bound-param update took effect; text read back");
CHECK(atomic_load(&execAffected) == 1, "dbExec reported the correct rows-affected");
CHECK(reportedScore == 7.25, "the double precision column read back as a real");
CHECK(atomic_load(&reportedOk) == false, "the boolean column read back as a bool");
CHECK(atomic_load(&reportedBlobLen) == 3, "a bytea param with an embedded NUL round-tripped at full length");
CHECK(reportedBlob[0] == 'x' && reportedBlob[1] == '\0' && reportedBlob[2] == 'y', "the embedded NUL survived the Postgres bound-param round-trip");
calogContextClose(ctx);
calogDestroy(calog);
calogDbShutdown();
printf("\n%d checks, %d failed\n", testsRun, testsFailed);
fflush(stdout);
return (testsFailed != 0) ? 1 : 0;
}

253
tests/testExport.c Normal file
View file

@ -0,0 +1,253 @@
// testExport.c -- exercises the export library. One Lua context publishes a function with
// export(); another Lua context calls it by its BARE name (via the globals __index resolver);
// a JavaScript context calls it via call. All calls run in the exporter's context.
#define _POSIX_C_SOURCE 200809L
#include "calog.h"
#include "calogExport.h"
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define CHECK(cond, msg) checkImpl((cond), (msg), __FILE__, __LINE__)
#define PUMP_LIMIT 4000
// s7 interns a handful of permanent strings it never frees (by design); suppress those so
// the leak checker still catches real leaks in the export paths.
const char *__lsan_default_suppressions(void);
const char *__lsan_default_suppressions(void) {
return "leak:make_permanent_string\n";
}
#define RESULT_SLOTS 12
static CalogT *calog = NULL;
static _Atomic int64_t results[RESULT_SLOTS];
static _Atomic bool exporterReady = false;
static _Atomic int32_t doneCount = 0;
static _Atomic int32_t errorCount = 0;
static int32_t testsRun = 0;
static int32_t testsFailed = 0;
static void checkImpl(bool condition, const char *message, const char *file, int32_t line);
static int64_t asInt(const CalogValueT *value);
static int32_t nativeDone(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t nativeReady(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t nativeReport(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static void onError(uint64_t contextId, const char *message, void *userData);
static void pumpUntilDone(int32_t target);
static void pumpUntilReady(void);
static int64_t asInt(const CalogValueT *value) {
if (value->type == calogIntE) {
return value->as.i;
}
return (int64_t)value->as.r;
}
static void checkImpl(bool condition, const char *message, const char *file, int32_t line) {
testsRun++;
if (!condition) {
testsFailed++;
printf("FAIL %s:%d %s\n", file, line, message);
}
}
static int32_t nativeDone(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
(void)args;
(void)argCount;
(void)userData;
atomic_fetch_add(&doneCount, 1);
calogValueNil(result);
return calogOkE;
}
static int32_t nativeReady(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
(void)args;
(void)argCount;
(void)userData;
atomic_store(&exporterReady, true);
calogValueNil(result);
return calogOkE;
}
static int32_t nativeReport(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
int64_t tag;
(void)userData;
calogValueNil(result);
if (argCount != 2 || (args[0].type != calogIntE && args[0].type != calogRealE) || (args[1].type != calogIntE && args[1].type != calogRealE)) {
return calogFail(result, calogErrArgE, "report expects (tag, value)");
}
tag = asInt(&args[0]);
if (tag < 0 || tag >= RESULT_SLOTS) {
return calogFail(result, calogErrArgE, "report: tag out of range");
}
atomic_store(&results[tag], asInt(&args[1]));
return calogOkE;
}
static void onError(uint64_t contextId, const char *message, void *userData) {
(void)contextId;
(void)userData;
fprintf(stderr, " [script error] %s\n", (message != NULL) ? message : "(null)");
atomic_fetch_add(&errorCount, 1);
}
static void pumpUntilDone(int32_t target) {
struct timespec ts = { 0, 500000 };
int i;
for (i = 0; i < PUMP_LIMIT; i++) {
calogPump(calog);
if (atomic_load(&doneCount) >= target) {
calogPump(calog);
return;
}
nanosleep(&ts, NULL);
}
}
static void pumpUntilReady(void) {
struct timespec ts = { 0, 500000 };
int i;
for (i = 0; i < PUMP_LIMIT; i++) {
calogPump(calog);
if (atomic_load(&exporterReady) || atomic_load(&errorCount) != 0) {
return;
}
nanosleep(&ts, NULL);
}
}
int main(void) {
CalogContextT *exporter;
CalogContextT *luaCaller;
CalogContextT *jsCaller;
CalogContextT *s7Caller;
CalogContextT *squirrelCaller;
CalogContextT *reloadV1;
CalogContextT *reloadV2;
int32_t i;
calog = calogCreate();
if (calog == NULL) {
printf("calog create failed\n");
return 1;
}
calogSetErrorHandler(calog, onError, NULL);
calogRegister(calog, "report", nativeReport, NULL);
calogRegister(calog, "done", nativeDone, NULL);
calogRegister(calog, "exporterReady", nativeReady, NULL);
if (calogExportRegister(calog) != calogOkE) {
printf("calogExportRegister failed\n");
return 1;
}
for (i = 0; i < RESULT_SLOTS; i++) {
atomic_store(&results[i], -1);
}
// Publisher: define a function and export it. It must stay open so calls can run in it.
exporter = calogContextOpen(calog, &calogLuaEngine);
calogContextEval(exporter,
"local function adder(a, b) return a + b end\n"
"export('adder', adder)\n"
"exporterReady()");
pumpUntilReady();
// A different Lua context calls the exported function by its BARE name and via call.
luaCaller = calogContextOpen(calog, &calogLuaEngine);
calogContextEval(luaCaller,
"report(1, adder(2, 3))\n"
"report(2, call('adder', 10, 20))\n"
"done()");
// A JavaScript context reaches the same Lua function via call, then by BARE name.
jsCaller = calogContextOpen(calog, &calogJsEngine);
calogContextEval(jsCaller,
"report(3, call('adder', 100, 1));\n"
"report(8, adder(9, 1));\n"
"done();");
// Bare-name resolution in the other clean engines: s7 (unbound-variable hook) and
// Squirrel (root-table _get delegate).
s7Caller = calogContextOpen(calog, &calogS7Engine);
calogContextEval(s7Caller, "(begin (report 6 (adder 100 5)) (done))");
squirrelCaller = calogContextOpen(calog, &calogSquirrelEngine);
calogContextEval(squirrelCaller,
"report(7, adder(50, 5));\n"
"done();");
pumpUntilDone(4);
CHECK(atomic_load(&results[1]) == 5, "a Lua script called an exported function by its bare name");
CHECK(atomic_load(&results[2]) == 30, "call reached the same exported function");
CHECK(atomic_load(&results[3]) == 101, "a JavaScript script called the exported Lua function via call");
CHECK(atomic_load(&results[8]) == 10, "a JavaScript script called the export by its bare name");
CHECK(atomic_load(&results[6]) == 105, "an s7 script called the export by its bare name");
CHECK(atomic_load(&results[7]) == 55, "a Squirrel script called the export by its bare name");
CHECK(atomic_load(&errorCount) == 0, "no errors during export/import");
// Hot-reload: a script exports a function, is unloaded, then a NEW version re-exports the
// same name. Re-exporting releases the old exported function -- whose owner context is now
// gone -- which must free its struct directly instead of running the engine release on the
// destroyed interpreter. Callers must then see the new version.
reloadV1 = calogContextOpen(calog, &calogLuaEngine);
atomic_store(&exporterReady, false);
calogContextEval(reloadV1,
"local function greet() return 111 end\n"
"export('greet', greet)\n"
"exporterReady()");
pumpUntilReady();
calogContextEval(luaCaller, "report(4, call('greet'))\n done()");
pumpUntilDone(5);
calogContextClose(reloadV1); // greet stays exported, but its owner is gone
reloadV2 = calogContextOpen(calog, &calogLuaEngine);
atomic_store(&exporterReady, false);
calogContextEval(reloadV2,
"local function greet() return 222 end\n"
"export('greet', greet)\n" // releases the old, dead-owner greet
"exporterReady()");
pumpUntilReady();
calogContextEval(luaCaller, "report(5, call('greet'))\n done()");
pumpUntilDone(6);
CHECK(atomic_load(&results[4]) == 111, "an exported function is callable before reload");
CHECK(atomic_load(&results[5]) == 222, "a reloaded script re-exports a new version after the old owner unloaded");
calogContextClose(reloadV2);
// Release exports while the runtime + contexts are still alive, then tear the runtime down.
calogExportShutdown();
// Regression: after shutdown, an unknown-global read still routes through __exportResolve
// (via the _G __index) -- the static registry must keep it safe, not a freed-state UAF.
calogContextEval(luaCaller, "local x = someUndefinedGlobalName\n done()");
pumpUntilDone(7);
CHECK(atomic_load(&doneCount) >= 7, "resolving an unknown global after export shutdown is safe");
calogContextClose(luaCaller);
calogContextClose(jsCaller);
calogContextClose(s7Caller);
calogContextClose(squirrelCaller);
calogContextClose(exporter);
calogDestroy(calog);
printf("\n%d checks, %d failed\n", testsRun, testsFailed);
fflush(stdout);
if (testsFailed != 0) {
return 1;
}
return 0;
}

View file

@ -16,6 +16,15 @@
#include <stdlib.h>
#include <time.h>
// This test loads a .scm script, so it spins up an s7 interpreter, which keeps a small,
// bounded set of interned "permanent" strings that s7_free intentionally never reclaims
// (an s7 design characteristic, not a calog defect). Suppress exactly that allocation
// site so the leak check stays meaningful. LSan calls this weak hook automatically.
const char *__lsan_default_suppressions(void);
const char *__lsan_default_suppressions(void) {
return "leak:make_permanent_string\n";
}
#define CHECK(cond, msg) checkImpl((cond), (msg), __FILE__, __LINE__)
#define PUMP_LIMIT 4000 // ~2s at 0.5ms/iter

367
tests/testNet.c Normal file
View file

@ -0,0 +1,367 @@
// testNet.c -- exercises the calog network library over loopback. Each test runs two
// concurrent scripts on separate context threads: a server (listen/bind, then blocking
// accept/recv) and a client (connect/send). A serverReady signal gates the client so there
// is no bind/connect race. Covers TCP (stream round-trip) and UDP (datagram round-trip,
// including the sender address reported by udpRecvFrom).
#define _POSIX_C_SOURCE 200809L
#include "calog.h"
#include "calogNet.h"
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define CHECK(cond, msg) checkImpl((cond), (msg), __FILE__, __LINE__)
#define PUMP_LIMIT 8000
#define TCP_PORT 47811
#define UDP_PORT 47812
#define ENET_PORT 47813
static CalogT *calog = NULL;
static _Atomic bool serverListening = false;
static _Atomic int32_t finishedCount = 0;
static _Atomic int32_t errorCount = 0;
static char serverGot[64] = { 0 };
static _Atomic int32_t serverGotLen = -1;
static char clientGot[64] = { 0 };
static _Atomic int32_t clientGotLen = -1;
static int32_t testsRun = 0;
static int32_t testsFailed = 0;
static void checkImpl(bool condition, const char *message, const char *file, int32_t line);
static void copyReport(CalogValueT *arg, char *dest, _Atomic int32_t *lenOut);
static int32_t nativeFinished(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t nativeReportClient(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t nativeReportServer(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t nativeServerReady(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static void onError(uint64_t contextId, const char *message, void *userData);
static void pumpUntilFinished(void);
static void pumpUntilListening(void);
static void resetState(void);
static void testEnet(void);
static void testEnetSafety(void);
static void testTcp(void);
static void testUdp(void);
static void checkImpl(bool condition, const char *message, const char *file, int32_t line) {
testsRun++;
if (!condition) {
testsFailed++;
printf("FAIL %s:%d %s\n", file, line, message);
}
}
static void copyReport(CalogValueT *arg, char *dest, _Atomic int32_t *lenOut) {
size_t length;
length = (size_t)arg->as.s.length;
if (length >= 64) {
length = 63;
}
memcpy(dest, arg->as.s.bytes, length);
dest[length] = '\0';
atomic_store(lenOut, (int32_t)length);
}
static int32_t nativeFinished(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
(void)args;
(void)argCount;
(void)userData;
atomic_fetch_add(&finishedCount, 1);
calogValueNil(result);
return calogOkE;
}
static int32_t nativeReportClient(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
(void)userData;
calogValueNil(result);
if (argCount != 1 || args[0].type != calogStringE) {
return calogFail(result, calogErrArgE, "reportClient expects one string");
}
copyReport(&args[0], clientGot, &clientGotLen);
return calogOkE;
}
static int32_t nativeReportServer(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
(void)userData;
calogValueNil(result);
if (argCount != 1 || args[0].type != calogStringE) {
return calogFail(result, calogErrArgE, "reportServer expects one string");
}
copyReport(&args[0], serverGot, &serverGotLen);
return calogOkE;
}
static int32_t nativeServerReady(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
(void)args;
(void)argCount;
(void)userData;
atomic_store(&serverListening, true);
calogValueNil(result);
return calogOkE;
}
static void onError(uint64_t contextId, const char *message, void *userData) {
(void)contextId;
(void)userData;
fprintf(stderr, " [script error] %s\n", (message != NULL) ? message : "(null)");
atomic_fetch_add(&errorCount, 1);
}
static void pumpUntilFinished(void) {
struct timespec ts = { 0, 500000 };
int i;
for (i = 0; i < PUMP_LIMIT; i++) {
calogPump(calog);
if (atomic_load(&finishedCount) >= 2) {
return;
}
nanosleep(&ts, NULL);
}
}
static void pumpUntilListening(void) {
struct timespec ts = { 0, 500000 };
int i;
for (i = 0; i < PUMP_LIMIT; i++) {
calogPump(calog);
if (atomic_load(&serverListening) || atomic_load(&errorCount) != 0) {
return;
}
nanosleep(&ts, NULL);
}
}
static void resetState(void) {
atomic_store(&serverListening, false);
atomic_store(&finishedCount, 0);
atomic_store(&serverGotLen, -1);
atomic_store(&clientGotLen, -1);
memset(serverGot, 0, sizeof(serverGot));
memset(clientGot, 0, sizeof(clientGot));
}
static void testEnet(void) {
CalogContextT *server;
CalogContextT *client;
char serverScript[768];
char clientScript[768];
resetState();
// Server: echo each reliable packet, stop when the client disconnects.
snprintf(serverScript, sizeof(serverScript),
"local host = enetHost(%d, 4)\n"
"serverReady()\n"
"local running = true\n"
"local count = 0\n"
"while running and count < 2000 do\n"
" local ev = enetService(host, 50)\n"
" if ev.type == 'receive' then\n"
" reportServer(ev.data)\n"
" enetSend(ev.peer, 0, 'pong:' .. ev.data, true)\n"
" elseif ev.type == 'disconnect' then\n"
" running = false\n"
" end\n"
" count = count + 1\n"
"end\n"
"enetClose(host)\n"
"finished()", ENET_PORT);
// Client: connect, send once, read the reply, then disconnect gracefully.
snprintf(clientScript, sizeof(clientScript),
"local host = enetHost(0, 1)\n"
"local peer = enetConnect(host, '127.0.0.1', %d, 1)\n"
"local finishedClient = false\n"
"local count = 0\n"
"while not finishedClient and count < 2000 do\n"
" local ev = enetService(host, 50)\n"
" if ev.type == 'connect' then\n"
" enetSend(peer, 0, 'hi', true)\n"
" elseif ev.type == 'receive' then\n"
" reportClient(ev.data)\n"
" enetDisconnect(peer)\n"
" elseif ev.type == 'disconnect' then\n"
" finishedClient = true\n"
" end\n"
" count = count + 1\n"
"end\n"
"enetClose(host)\n"
"finished()", ENET_PORT);
server = calogContextOpen(calog, &calogLuaEngine);
calogContextEval(server, serverScript);
pumpUntilListening();
client = calogContextOpen(calog, &calogLuaEngine);
calogContextEval(client, clientScript);
pumpUntilFinished();
CHECK(strcmp(serverGot, "hi") == 0, "ENet server received the reliable packet");
CHECK(strcmp(clientGot, "pong:hi") == 0, "ENet client received the reliable reply over its peer");
CHECK(atomic_load(&errorCount) == 0, "no errors during the ENet round-trip");
calogContextClose(server);
calogContextClose(client);
}
static void testEnetSafety(void) {
CalogContextT *ctx;
struct timespec ts = { 0, 500000 };
int32_t before;
int i;
resetState();
before = atomic_load(&errorCount);
ctx = calogContextOpen(calog, &calogLuaEngine);
// Using a peer handle after its host is closed must raise a clean script error, NOT a
// use-after-free (enetClose drops the host's peer handles). ASan would flag any UAF.
calogContextEval(ctx,
"local h = enetHost(0, 1)\n"
"local p = enetConnect(h, '127.0.0.1', 59999, 1)\n"
"enetClose(h)\n"
"enetSend(p, 0, 'x', true)\n"
"done()");
for (i = 0; i < PUMP_LIMIT; i++) {
calogPump(calog);
if (atomic_load(&errorCount) > before) {
break;
}
nanosleep(&ts, NULL);
}
CHECK(atomic_load(&errorCount) > before, "using an ENet peer handle after enetClose is a clean error, not a use-after-free");
calogContextClose(ctx);
}
static void testTcp(void) {
CalogContextT *server;
CalogContextT *client;
char serverScript[512];
char clientScript[512];
resetState();
snprintf(serverScript, sizeof(serverScript),
"local l = tcpListen(%d)\n"
"serverReady()\n"
"local c = tcpAccept(l)\n"
"local d = tcpRecv(c, 100)\n"
"reportServer(d)\n"
"tcpSend(c, 'pong:' .. d)\n"
"tcpClose(c)\n"
"tcpClose(l)\n"
"finished()", TCP_PORT);
snprintf(clientScript, sizeof(clientScript),
"local c = tcpConnect('127.0.0.1', %d)\n"
"tcpSend(c, 'ping')\n"
"local r = tcpRecv(c, 100)\n"
"reportClient(r)\n"
"tcpClose(c)\n"
"finished()", TCP_PORT);
server = calogContextOpen(calog, &calogLuaEngine);
calogContextEval(server, serverScript);
pumpUntilListening();
client = calogContextOpen(calog, &calogLuaEngine);
calogContextEval(client, clientScript);
pumpUntilFinished();
CHECK(strcmp(serverGot, "ping") == 0, "TCP server received the client's stream payload");
CHECK(strcmp(clientGot, "pong:ping") == 0, "TCP client received the server's reply");
CHECK(atomic_load(&errorCount) == 0, "no errors during the TCP round-trip");
calogContextClose(server);
calogContextClose(client);
}
static void testUdp(void) {
CalogContextT *server;
CalogContextT *client;
char serverScript[512];
char clientScript[512];
resetState();
// The server replies to the address udpRecvFrom reports, so the client need not bind a
// known port -- this also checks the {data, host, port} map.
snprintf(serverScript, sizeof(serverScript),
"local s = udpOpen(%d)\n"
"serverReady()\n"
"local m = udpRecvFrom(s, 100)\n"
"reportServer(m.data)\n"
"udpSendTo(s, m.host, m.port, 'pong:' .. m.data)\n"
"udpClose(s)\n"
"finished()", UDP_PORT);
snprintf(clientScript, sizeof(clientScript),
"local c = udpOpen(0)\n"
"udpSendTo(c, '127.0.0.1', %d, 'hi')\n"
"local m = udpRecvFrom(c, 100)\n"
"reportClient(m.data)\n"
"udpClose(c)\n"
"finished()", UDP_PORT);
server = calogContextOpen(calog, &calogLuaEngine);
calogContextEval(server, serverScript);
pumpUntilListening();
client = calogContextOpen(calog, &calogLuaEngine);
calogContextEval(client, clientScript);
pumpUntilFinished();
CHECK(strcmp(serverGot, "hi") == 0, "UDP server received the datagram");
CHECK(strcmp(clientGot, "pong:hi") == 0, "UDP client received the reply routed to its reported address");
CHECK(atomic_load(&errorCount) == 0, "no errors during the UDP round-trip");
calogContextClose(server);
calogContextClose(client);
}
int main(void) {
calog = calogCreate();
if (calog == NULL) {
printf("calog create failed\n");
return 1;
}
calogSetErrorHandler(calog, onError, NULL);
calogRegister(calog, "serverReady", nativeServerReady, NULL);
calogRegister(calog, "reportServer", nativeReportServer, NULL);
calogRegister(calog, "reportClient", nativeReportClient, NULL);
calogRegister(calog, "finished", nativeFinished, NULL);
if (calogNetRegister(calog) != calogOkE) {
printf("calogNetRegister failed\n");
return 1;
}
testTcp();
testUdp();
testEnet();
testEnetSafety();
calogDestroy(calog);
calogNetShutdown();
printf("\n%d checks, %d failed\n", testsRun, testsFailed);
fflush(stdout);
if (testsFailed != 0) {
return 1;
}
return 0;
}

320
tests/testTask.c Normal file
View file

@ -0,0 +1,320 @@
// testTask.c -- exercises the calog task library: a parent Lua script spawns child script
// contexts, feeds them code, queries the task count and its own id, loads a script file, and
// closes tasks. Children report values back through a host native so the parent's management
// of them can be observed.
#define _POSIX_C_SOURCE 200809L
#include "calog.h"
#include "calogTask.h"
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define CHECK(cond, msg) checkImpl((cond), (msg), __FILE__, __LINE__)
#define PUMP_LIMIT 4000
#define TAG_COUNT 16
static CalogT *calog = NULL;
static _Atomic int64_t results[TAG_COUNT];
static _Atomic bool scriptDone = false;
static _Atomic int32_t errorCount = 0;
static int32_t testsRun = 0;
static int32_t testsFailed = 0;
static void checkImpl(bool condition, const char *message, const char *file, int32_t line);
static int32_t nativeDone(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static int32_t nativeReport(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
static void onError(uint64_t contextId, const char *message, void *userData);
static void pumpUntilDone(void);
static void pumpUntilScriptDone(void);
static void resetTags(void);
static void testTaskCrossEngine(void);
static void testTaskError(void);
static void testTaskLoad(void);
static void testTaskMutualClose(void);
static void testTaskSelfClose(void);
static void testTaskSpawn(void);
static void writeFile(const char *path, const char *text);
static void checkImpl(bool condition, const char *message, const char *file, int32_t line) {
testsRun++;
if (!condition) {
testsFailed++;
printf("FAIL %s:%d %s\n", file, line, message);
}
}
static int32_t nativeDone(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
(void)args;
(void)argCount;
(void)userData;
atomic_store(&scriptDone, true);
calogValueNil(result);
return calogOkE;
}
// Accept int or real so the same observer works from every engine (e.g. JS numbers marshal
// as reals).
static int64_t asInt(const CalogValueT *value) {
if (value->type == calogIntE) {
return value->as.i;
}
return (int64_t)value->as.r;
}
static int32_t nativeReport(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
int64_t tag;
(void)userData;
calogValueNil(result);
if (argCount != 2 || (args[0].type != calogIntE && args[0].type != calogRealE) || (args[1].type != calogIntE && args[1].type != calogRealE)) {
return calogFail(result, calogErrArgE, "report expects (tag, value)");
}
tag = asInt(&args[0]);
if (tag < 0 || tag >= TAG_COUNT) {
return calogFail(result, calogErrArgE, "report: tag out of range");
}
atomic_store(&results[tag], asInt(&args[1]));
return calogOkE;
}
static void onError(uint64_t contextId, const char *message, void *userData) {
(void)contextId;
(void)userData;
fprintf(stderr, " [script error] %s\n", (message != NULL) ? message : "(null)");
atomic_fetch_add(&errorCount, 1);
}
static void pumpUntilDone(void) {
struct timespec ts = { 0, 500000 };
int errorsBefore;
int i;
errorsBefore = atomic_load(&errorCount);
for (i = 0; i < PUMP_LIMIT; i++) {
calogPump(calog);
if (atomic_load(&scriptDone) || atomic_load(&errorCount) != errorsBefore) {
calogPump(calog);
return;
}
nanosleep(&ts, NULL);
}
}
// Waits for the parent script's done() regardless of child errors (used by tests that
// deliberately trigger a refused operation in a child but expect the parent to finish).
static void pumpUntilScriptDone(void) {
struct timespec ts = { 0, 500000 };
int i;
for (i = 0; i < PUMP_LIMIT; i++) {
calogPump(calog);
if (atomic_load(&scriptDone)) {
calogPump(calog);
calogPump(calog);
return;
}
nanosleep(&ts, NULL);
}
}
static void resetTags(void) {
int32_t i;
atomic_store(&scriptDone, false);
for (i = 0; i < TAG_COUNT; i++) {
atomic_store(&results[i], -1);
}
}
static void testTaskCrossEngine(void) {
CalogContextT *ctx;
ctx = calogContextOpen(calog, &calogLuaEngine);
resetTags();
// A Lua script launches a JavaScript task -- the whole point of naming the engine.
calogContextEval(ctx,
"local j = taskSpawn('js', 'report(8, 55)')\n"
"taskClose(j)\n"
"done()");
pumpUntilDone();
CHECK(atomic_load(&results[8]) == 55, "a Lua script spawned and ran a JavaScript task");
calogContextClose(ctx);
}
static void testTaskError(void) {
CalogContextT *ctx;
int32_t before;
ctx = calogContextOpen(calog, &calogLuaEngine);
before = atomic_load(&errorCount);
resetTags();
// Spawning an unknown engine must raise a clean script-level error.
calogContextEval(ctx, "taskSpawn('nosuchengine', 'return 1')\n done()");
pumpUntilDone();
CHECK(atomic_load(&errorCount) == before + 1, "taskSpawn of an unknown engine raised a script error");
calogContextClose(ctx);
}
static void testTaskLoad(void) {
CalogContextT *ctx;
writeFile("clTask.lua", "report(6, 77)\n");
ctx = calogContextOpen(calog, &calogLuaEngine);
resetTags();
// taskLoad launches the script FILE by base name; it reports 77, then we close it.
calogContextEval(ctx,
"local f = taskLoad('clTask')\n"
"taskClose(f)\n"
"done()");
pumpUntilDone();
CHECK(atomic_load(&results[6]) == 77, "taskLoad launched a script file that ran");
calogContextClose(ctx);
remove("clTask.lua");
}
static void testTaskMutualClose(void) {
CalogContextT *ctx;
ctx = calogContextOpen(calog, &calogLuaEngine);
resetTags();
// Two children each told to close the OTHER's handle. Both are refused (the parent owns
// both), so there is no mutual pthread_join deadlock -- reaching the end proves it.
calogContextEval(ctx,
"local a = taskSpawn('lua', '')\n"
"local b = taskSpawn('lua', '')\n"
"taskEval(a, 'taskClose(' .. b .. ')')\n"
"taskEval(b, 'taskClose(' .. a .. ')')\n"
"taskClose(a)\n"
"taskClose(b)\n"
"report(1, 1)\n"
"done()");
pumpUntilScriptDone();
CHECK(atomic_load(&results[1]) == 1, "mutual cross-close is refused, not a deadlock");
calogContextClose(ctx);
}
static void testTaskSelfClose(void) {
CalogContextT *ctx;
int32_t before;
ctx = calogContextOpen(calog, &calogLuaEngine);
before = atomic_load(&errorCount);
resetTags();
// A child is told to close its OWN handle. That must be refused (only the owner closes),
// NOT a self-join that frees the running context -- reaching the end proves no crash.
calogContextEval(ctx,
"local t = taskSpawn('lua', '')\n"
"taskEval(t, 'taskClose(' .. t .. ')')\n"
"taskClose(t)\n"
"report(1, 1)\n"
"done()");
pumpUntilScriptDone();
CHECK(atomic_load(&results[1]) == 1, "a task closing its own handle is refused, not a self-join crash");
CHECK(atomic_load(&errorCount) > before, "the self-close attempt raised a clean error");
calogContextClose(ctx);
}
static void testTaskSpawn(void) {
CalogContextT *ctx;
ctx = calogContextOpen(calog, &calogLuaEngine);
resetTags();
// Spawn a child (reports 42), read the live task count + own id, feed the child more code
// (reports 99), close it, then read the count again.
calogContextEval(ctx,
"local t = taskSpawn('lua', 'report(1, 42)')\n"
"report(2, taskCount())\n"
"report(3, taskSelf())\n"
"taskEval(t, 'report(4, 99)')\n"
"taskClose(t)\n"
"report(5, taskCount())\n"
"done()");
pumpUntilDone();
CHECK(atomic_load(&results[1]) == 42, "a spawned child task ran its code");
CHECK(atomic_load(&results[2]) == 1, "taskCount saw the one open task");
CHECK(atomic_load(&results[3]) > 0, "taskSelf returned the caller's own non-zero context id");
CHECK(atomic_load(&results[4]) == 99, "taskEval fed more code into the running task");
CHECK(atomic_load(&results[5]) == 0, "taskCount saw the task gone after taskClose");
calogContextClose(ctx);
}
static void writeFile(const char *path, const char *text) {
FILE *file;
file = fopen(path, "wb");
if (file == NULL) {
return;
}
fwrite(text, 1, strlen(text), file);
fclose(file);
}
int main(void) {
calog = calogCreate();
if (calog == NULL) {
printf("calog create failed\n");
return 1;
}
calogSetErrorHandler(calog, onError, NULL);
calogRegisterEngine(calog, &calogLuaEngine); // so taskLoad can find *.lua
// Inline observers: they run on the reporting task's own thread and complete within its
// eval, so they are not aborted when a task is closed mid-report (unlike a host native,
// whose cross-thread call taskClose's cooperative shutdown can interrupt).
calogRegisterInline(calog, "report", nativeReport, NULL);
calogRegisterInline(calog, "done", nativeDone, NULL);
if (calogTaskRegister(calog) != calogOkE) {
printf("calogTaskRegister failed\n");
return 1;
}
testTaskSpawn();
testTaskLoad();
testTaskCrossEngine();
testTaskSelfClose();
testTaskMutualClose();
testTaskError();
calogDestroy(calog);
calogTaskShutdown();
printf("\n%d checks, %d failed\n", testsRun, testsFailed);
fflush(stdout);
if (testsFailed != 0) {
return 1;
}
return 0;
}

1
vendor/enet/COMMIT.txt vendored Normal file
View file

@ -0,0 +1 @@
5a9c537fd464b3c6d3c55e1d3bd47588faf71b42 2026-06-23 15:17:21 -0400

7
vendor/enet/LICENSE vendored Normal file
View file

@ -0,0 +1,7 @@
Copyright (c) 2002-2024 Lee Salzman
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

53
vendor/enet/callbacks.c vendored Normal file
View file

@ -0,0 +1,53 @@
/**
@file callbacks.c
@brief ENet callback functions
*/
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
static ENetCallbacks callbacks = { malloc, free, abort };
int
enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits)
{
if (version < ENET_VERSION_CREATE (1, 3, 0))
return -1;
if (inits -> malloc != NULL || inits -> free != NULL)
{
if (inits -> malloc == NULL || inits -> free == NULL)
return -1;
callbacks.malloc = inits -> malloc;
callbacks.free = inits -> free;
}
if (inits -> no_memory != NULL)
callbacks.no_memory = inits -> no_memory;
return enet_initialize ();
}
ENetVersion
enet_linked_version (void)
{
return ENET_VERSION;
}
void *
enet_malloc (size_t size)
{
void * memory = callbacks.malloc (size);
if (memory == NULL)
callbacks.no_memory ();
return memory;
}
void
enet_free (void * memory)
{
callbacks.free (memory);
}

654
vendor/enet/compress.c vendored Normal file
View file

@ -0,0 +1,654 @@
/**
@file compress.c
@brief An adaptive order-2 PPM range coder
*/
#define ENET_BUILDING_LIB 1
#include <string.h>
#include "enet/enet.h"
typedef struct _ENetSymbol
{
/* binary indexed tree of symbols */
enet_uint8 value;
enet_uint8 count;
enet_uint16 under;
enet_uint16 left, right;
/* context defined by this symbol */
enet_uint16 symbols;
enet_uint16 escapes;
enet_uint16 total;
enet_uint16 parent;
} ENetSymbol;
/* adaptation constants tuned aggressively for small packet sizes rather than large file compression */
enum
{
ENET_RANGE_CODER_TOP = 1<<24,
ENET_RANGE_CODER_BOTTOM = 1<<16,
ENET_CONTEXT_SYMBOL_DELTA = 3,
ENET_CONTEXT_SYMBOL_MINIMUM = 1,
ENET_CONTEXT_ESCAPE_MINIMUM = 1,
ENET_SUBCONTEXT_ORDER = 2,
ENET_SUBCONTEXT_SYMBOL_DELTA = 2,
ENET_SUBCONTEXT_ESCAPE_DELTA = 5
};
/* context exclusion roughly halves compression speed, so disable for now */
#undef ENET_CONTEXT_EXCLUSION
typedef struct _ENetRangeCoder
{
/* only allocate enough symbols for reasonable MTUs, would need to be larger for large file compression */
ENetSymbol symbols[4096];
} ENetRangeCoder;
void *
enet_range_coder_create (void)
{
ENetRangeCoder * rangeCoder = (ENetRangeCoder *) enet_malloc (sizeof (ENetRangeCoder));
if (rangeCoder == NULL)
return NULL;
return rangeCoder;
}
void
enet_range_coder_destroy (void * context)
{
ENetRangeCoder * rangeCoder = (ENetRangeCoder *) context;
if (rangeCoder == NULL)
return;
enet_free (rangeCoder);
}
#define ENET_SYMBOL_CREATE(symbol, value_, count_) \
{ \
symbol = & rangeCoder -> symbols [nextSymbol ++]; \
symbol -> value = value_; \
symbol -> count = count_; \
symbol -> under = count_; \
symbol -> left = 0; \
symbol -> right = 0; \
symbol -> symbols = 0; \
symbol -> escapes = 0; \
symbol -> total = 0; \
symbol -> parent = 0; \
}
#define ENET_CONTEXT_CREATE(context, escapes_, minimum) \
{ \
ENET_SYMBOL_CREATE (context, 0, 0); \
(context) -> escapes = escapes_; \
(context) -> total = escapes_ + 256*minimum; \
(context) -> symbols = 0; \
}
static enet_uint16
enet_symbol_rescale (ENetSymbol * symbol)
{
enet_uint16 total = 0;
for (;;)
{
symbol -> count -= symbol->count >> 1;
symbol -> under = symbol -> count;
if (symbol -> left)
symbol -> under += enet_symbol_rescale (symbol + symbol -> left);
total += symbol -> under;
if (! symbol -> right) break;
symbol += symbol -> right;
}
return total;
}
#define ENET_CONTEXT_RESCALE(context, minimum) \
{ \
(context) -> total = (context) -> symbols ? enet_symbol_rescale ((context) + (context) -> symbols) : 0; \
(context) -> escapes -= (context) -> escapes >> 1; \
(context) -> total += (context) -> escapes + 256*minimum; \
}
#define ENET_RANGE_CODER_OUTPUT(value) \
{ \
if (outData >= outEnd) \
return 0; \
* outData ++ = value; \
}
#define ENET_RANGE_CODER_ENCODE(under, count, total) \
{ \
encodeRange /= (total); \
encodeLow += (under) * encodeRange; \
encodeRange *= (count); \
for (;;) \
{ \
if((encodeLow ^ (encodeLow + encodeRange)) >= ENET_RANGE_CODER_TOP) \
{ \
if(encodeRange >= ENET_RANGE_CODER_BOTTOM) break; \
encodeRange = -encodeLow & (ENET_RANGE_CODER_BOTTOM - 1); \
} \
ENET_RANGE_CODER_OUTPUT (encodeLow >> 24); \
encodeRange <<= 8; \
encodeLow <<= 8; \
} \
}
#define ENET_RANGE_CODER_FLUSH \
{ \
while (encodeLow) \
{ \
ENET_RANGE_CODER_OUTPUT (encodeLow >> 24); \
encodeLow <<= 8; \
} \
}
#define ENET_RANGE_CODER_FREE_SYMBOLS \
{ \
if (nextSymbol >= sizeof (rangeCoder -> symbols) / sizeof (ENetSymbol) - ENET_SUBCONTEXT_ORDER ) \
{ \
nextSymbol = 0; \
ENET_CONTEXT_CREATE (root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM); \
predicted = 0; \
order = 0; \
} \
}
#define ENET_CONTEXT_ENCODE(context, symbol_, value_, under_, count_, update, minimum) \
{ \
under_ = value*minimum; \
count_ = minimum; \
if (! (context) -> symbols) \
{ \
ENET_SYMBOL_CREATE (symbol_, value_, update); \
(context) -> symbols = symbol_ - (context); \
} \
else \
{ \
ENetSymbol * node = (context) + (context) -> symbols; \
for (;;) \
{ \
if (value_ < node -> value) \
{ \
node -> under += update; \
if (node -> left) { node += node -> left; continue; } \
ENET_SYMBOL_CREATE (symbol_, value_, update); \
node -> left = symbol_ - node; \
} \
else \
if (value_ > node -> value) \
{ \
under_ += node -> under; \
if (node -> right) { node += node -> right; continue; } \
ENET_SYMBOL_CREATE (symbol_, value_, update); \
node -> right = symbol_ - node; \
} \
else \
{ \
count_ += node -> count; \
under_ += node -> under - node -> count; \
node -> under += update; \
node -> count += update; \
symbol_ = node; \
} \
break; \
} \
} \
}
#ifdef ENET_CONTEXT_EXCLUSION
static const ENetSymbol emptyContext = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
#define ENET_CONTEXT_WALK(context, body) \
{ \
const ENetSymbol * node = (context) + (context) -> symbols; \
const ENetSymbol * stack [256]; \
size_t stackSize = 0; \
while (node -> left) \
{ \
stack [stackSize ++] = node; \
node += node -> left; \
} \
for (;;) \
{ \
body; \
if (node -> right) \
{ \
node += node -> right; \
while (node -> left) \
{ \
stack [stackSize ++] = node; \
node += node -> left; \
} \
} \
else \
if (stackSize <= 0) \
break; \
else \
node = stack [-- stackSize]; \
} \
}
#define ENET_CONTEXT_ENCODE_EXCLUDE(context, value_, under, total, minimum) \
ENET_CONTEXT_WALK(context, { \
if (node -> value != value_) \
{ \
enet_uint16 parentCount = rangeCoder -> symbols [node -> parent].count + minimum; \
if (node -> value < value_) \
under -= parentCount; \
total -= parentCount; \
} \
})
#endif
size_t
enet_range_coder_compress (void * context, const ENetBuffer * inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 * outData, size_t outLimit)
{
ENetRangeCoder * rangeCoder = (ENetRangeCoder *) context;
enet_uint8 * outStart = outData, * outEnd = & outData [outLimit];
const enet_uint8 * inData, * inEnd;
enet_uint32 encodeLow = 0, encodeRange = ~0;
ENetSymbol * root;
enet_uint16 predicted = 0;
size_t order = 0, nextSymbol = 0;
if (rangeCoder == NULL || inBufferCount <= 0 || inLimit <= 0)
return 0;
inData = (const enet_uint8 *) inBuffers -> data;
inEnd = & inData [inBuffers -> dataLength];
inBuffers ++;
inBufferCount --;
ENET_CONTEXT_CREATE (root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM);
for (;;)
{
ENetSymbol * subcontext, * symbol;
#ifdef ENET_CONTEXT_EXCLUSION
const ENetSymbol * childContext = & emptyContext;
#endif
enet_uint8 value;
enet_uint16 count, under, * parent = & predicted, total;
if (inData >= inEnd)
{
if (inBufferCount <= 0)
break;
inData = (const enet_uint8 *) inBuffers -> data;
inEnd = & inData [inBuffers -> dataLength];
inBuffers ++;
inBufferCount --;
}
value = * inData ++;
for (subcontext = & rangeCoder -> symbols [predicted];
subcontext != root;
#ifdef ENET_CONTEXT_EXCLUSION
childContext = subcontext,
#endif
subcontext = & rangeCoder -> symbols [subcontext -> parent])
{
ENET_CONTEXT_ENCODE (subcontext, symbol, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0);
* parent = symbol - rangeCoder -> symbols;
parent = & symbol -> parent;
total = subcontext -> total;
#ifdef ENET_CONTEXT_EXCLUSION
if (childContext -> total > ENET_SUBCONTEXT_SYMBOL_DELTA + ENET_SUBCONTEXT_ESCAPE_DELTA)
ENET_CONTEXT_ENCODE_EXCLUDE (childContext, value, under, total, 0);
#endif
if (count > 0)
{
ENET_RANGE_CODER_ENCODE (subcontext -> escapes + under, count, total);
}
else
{
if (subcontext -> escapes > 0 && subcontext -> escapes < total)
ENET_RANGE_CODER_ENCODE (0, subcontext -> escapes, total);
subcontext -> escapes += ENET_SUBCONTEXT_ESCAPE_DELTA;
subcontext -> total += ENET_SUBCONTEXT_ESCAPE_DELTA;
}
subcontext -> total += ENET_SUBCONTEXT_SYMBOL_DELTA;
if (count > 0xFF - 2*ENET_SUBCONTEXT_SYMBOL_DELTA || subcontext -> total > ENET_RANGE_CODER_BOTTOM - 0x100)
ENET_CONTEXT_RESCALE (subcontext, 0);
if (count > 0) goto nextInput;
}
ENET_CONTEXT_ENCODE (root, symbol, value, under, count, ENET_CONTEXT_SYMBOL_DELTA, ENET_CONTEXT_SYMBOL_MINIMUM);
* parent = symbol - rangeCoder -> symbols;
parent = & symbol -> parent;
total = root -> total;
#ifdef ENET_CONTEXT_EXCLUSION
if (childContext -> total > ENET_SUBCONTEXT_SYMBOL_DELTA + ENET_SUBCONTEXT_ESCAPE_DELTA)
ENET_CONTEXT_ENCODE_EXCLUDE (childContext, value, under, total, ENET_CONTEXT_SYMBOL_MINIMUM);
#endif
ENET_RANGE_CODER_ENCODE (root -> escapes + under, count, total);
root -> total += ENET_CONTEXT_SYMBOL_DELTA;
if (count > 0xFF - 2*ENET_CONTEXT_SYMBOL_DELTA + ENET_CONTEXT_SYMBOL_MINIMUM || root -> total > ENET_RANGE_CODER_BOTTOM - 0x100)
ENET_CONTEXT_RESCALE (root, ENET_CONTEXT_SYMBOL_MINIMUM);
nextInput:
if (order >= ENET_SUBCONTEXT_ORDER)
predicted = rangeCoder -> symbols [predicted].parent;
else
order ++;
ENET_RANGE_CODER_FREE_SYMBOLS;
}
ENET_RANGE_CODER_FLUSH;
return (size_t) (outData - outStart);
}
#define ENET_RANGE_CODER_SEED \
{ \
if (inData < inEnd) decodeCode |= * inData ++ << 24; \
if (inData < inEnd) decodeCode |= * inData ++ << 16; \
if (inData < inEnd) decodeCode |= * inData ++ << 8; \
if (inData < inEnd) decodeCode |= * inData ++; \
}
#define ENET_RANGE_CODER_READ(total) ((decodeCode - decodeLow) / (decodeRange /= (total)))
#define ENET_RANGE_CODER_DECODE(under, count, total) \
{ \
decodeLow += (under) * decodeRange; \
decodeRange *= (count); \
for (;;) \
{ \
if((decodeLow ^ (decodeLow + decodeRange)) >= ENET_RANGE_CODER_TOP) \
{ \
if(decodeRange >= ENET_RANGE_CODER_BOTTOM) break; \
decodeRange = -decodeLow & (ENET_RANGE_CODER_BOTTOM - 1); \
} \
decodeCode <<= 8; \
if (inData < inEnd) \
decodeCode |= * inData ++; \
decodeRange <<= 8; \
decodeLow <<= 8; \
} \
}
#define ENET_CONTEXT_DECODE(context, symbol_, code, value_, under_, count_, update, minimum, createRoot, visitNode, createRight, createLeft) \
{ \
under_ = 0; \
count_ = minimum; \
if (! (context) -> symbols) \
{ \
createRoot; \
} \
else \
{ \
ENetSymbol * node = (context) + (context) -> symbols; \
for (;;) \
{ \
enet_uint16 after = under_ + node -> under + (node -> value + 1)*minimum, before = node -> count + minimum; \
visitNode; \
if (code >= after) \
{ \
under_ += node -> under; \
if (node -> right) { node += node -> right; continue; } \
createRight; \
} \
else \
if (code < after - before) \
{ \
node -> under += update; \
if (node -> left) { node += node -> left; continue; } \
createLeft; \
} \
else \
{ \
value_ = node -> value; \
count_ += node -> count; \
under_ = after - before; \
node -> under += update; \
node -> count += update; \
symbol_ = node; \
} \
break; \
} \
} \
}
#define ENET_CONTEXT_TRY_DECODE(context, symbol_, code, value_, under_, count_, update, minimum, exclude) \
ENET_CONTEXT_DECODE (context, symbol_, code, value_, under_, count_, update, minimum, return 0, exclude (node -> value, after, before), return 0, return 0)
#define ENET_CONTEXT_ROOT_DECODE(context, symbol_, code, value_, under_, count_, update, minimum, exclude) \
ENET_CONTEXT_DECODE (context, symbol_, code, value_, under_, count_, update, minimum, \
{ \
value_ = code / minimum; \
under_ = code - code%minimum; \
ENET_SYMBOL_CREATE (symbol_, value_, update); \
(context) -> symbols = symbol_ - (context); \
}, \
exclude (node -> value, after, before), \
{ \
value_ = node->value + 1 + (code - after)/minimum; \
under_ = code - (code - after)%minimum; \
ENET_SYMBOL_CREATE (symbol_, value_, update); \
node -> right = symbol_ - node; \
}, \
{ \
value_ = node->value - 1 - (after - before - code - 1)/minimum; \
under_ = code - (after - before - code - 1)%minimum; \
ENET_SYMBOL_CREATE (symbol_, value_, update); \
node -> left = symbol_ - node; \
}) \
#ifdef ENET_CONTEXT_EXCLUSION
typedef struct _ENetExclude
{
enet_uint8 value;
enet_uint16 under;
} ENetExclude;
#define ENET_CONTEXT_DECODE_EXCLUDE(context, total, minimum) \
{ \
enet_uint16 under = 0; \
nextExclude = excludes; \
ENET_CONTEXT_WALK (context, { \
under += rangeCoder -> symbols [node -> parent].count + minimum; \
nextExclude -> value = node -> value; \
nextExclude -> under = under; \
nextExclude ++; \
}); \
total -= under; \
}
#define ENET_CONTEXT_EXCLUDED(value_, after, before) \
{ \
size_t low = 0, high = nextExclude - excludes; \
for(;;) \
{ \
size_t mid = (low + high) >> 1; \
const ENetExclude * exclude = & excludes [mid]; \
if (value_ < exclude -> value) \
{ \
if (low + 1 < high) \
{ \
high = mid; \
continue; \
} \
if (exclude > excludes) \
after -= exclude [-1].under; \
} \
else \
{ \
if (value_ > exclude -> value) \
{ \
if (low + 1 < high) \
{ \
low = mid; \
continue; \
} \
} \
else \
before = 0; \
after -= exclude -> under; \
} \
break; \
} \
}
#endif
#define ENET_CONTEXT_NOT_EXCLUDED(value_, after, before)
size_t
enet_range_coder_decompress (void * context, const enet_uint8 * inData, size_t inLimit, enet_uint8 * outData, size_t outLimit)
{
ENetRangeCoder * rangeCoder = (ENetRangeCoder *) context;
enet_uint8 * outStart = outData, * outEnd = & outData [outLimit];
const enet_uint8 * inEnd = & inData [inLimit];
enet_uint32 decodeLow = 0, decodeCode = 0, decodeRange = ~0;
ENetSymbol * root;
enet_uint16 predicted = 0;
size_t order = 0, nextSymbol = 0;
#ifdef ENET_CONTEXT_EXCLUSION
ENetExclude excludes [256];
ENetExclude * nextExclude = excludes;
#endif
if (rangeCoder == NULL || inLimit <= 0)
return 0;
ENET_CONTEXT_CREATE (root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM);
ENET_RANGE_CODER_SEED;
for (;;)
{
ENetSymbol * subcontext, * symbol, * patch;
#ifdef ENET_CONTEXT_EXCLUSION
const ENetSymbol * childContext = & emptyContext;
#endif
enet_uint8 value = 0;
enet_uint16 code, under, count, bottom, * parent = & predicted, total;
for (subcontext = & rangeCoder -> symbols [predicted];
subcontext != root;
#ifdef ENET_CONTEXT_EXCLUSION
childContext = subcontext,
#endif
subcontext = & rangeCoder -> symbols [subcontext -> parent])
{
if (subcontext -> escapes <= 0)
continue;
total = subcontext -> total;
#ifdef ENET_CONTEXT_EXCLUSION
if (childContext -> total > 0)
ENET_CONTEXT_DECODE_EXCLUDE (childContext, total, 0);
#endif
if (subcontext -> escapes >= total)
continue;
code = ENET_RANGE_CODER_READ (total);
if (code < subcontext -> escapes)
{
ENET_RANGE_CODER_DECODE (0, subcontext -> escapes, total);
continue;
}
code -= subcontext -> escapes;
#ifdef ENET_CONTEXT_EXCLUSION
if (childContext -> total > 0)
{
ENET_CONTEXT_TRY_DECODE (subcontext, symbol, code, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0, ENET_CONTEXT_EXCLUDED);
}
else
#endif
{
ENET_CONTEXT_TRY_DECODE (subcontext, symbol, code, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0, ENET_CONTEXT_NOT_EXCLUDED);
}
bottom = symbol - rangeCoder -> symbols;
ENET_RANGE_CODER_DECODE (subcontext -> escapes + under, count, total);
subcontext -> total += ENET_SUBCONTEXT_SYMBOL_DELTA;
if (count > 0xFF - 2*ENET_SUBCONTEXT_SYMBOL_DELTA || subcontext -> total > ENET_RANGE_CODER_BOTTOM - 0x100)
ENET_CONTEXT_RESCALE (subcontext, 0);
goto patchContexts;
}
total = root -> total;
#ifdef ENET_CONTEXT_EXCLUSION
if (childContext -> total > 0)
ENET_CONTEXT_DECODE_EXCLUDE (childContext, total, ENET_CONTEXT_SYMBOL_MINIMUM);
#endif
code = ENET_RANGE_CODER_READ (total);
if (code < root -> escapes)
{
ENET_RANGE_CODER_DECODE (0, root -> escapes, total);
break;
}
code -= root -> escapes;
#ifdef ENET_CONTEXT_EXCLUSION
if (childContext -> total > 0)
{
ENET_CONTEXT_ROOT_DECODE (root, symbol, code, value, under, count, ENET_CONTEXT_SYMBOL_DELTA, ENET_CONTEXT_SYMBOL_MINIMUM, ENET_CONTEXT_EXCLUDED);
}
else
#endif
{
ENET_CONTEXT_ROOT_DECODE (root, symbol, code, value, under, count, ENET_CONTEXT_SYMBOL_DELTA, ENET_CONTEXT_SYMBOL_MINIMUM, ENET_CONTEXT_NOT_EXCLUDED);
}
bottom = symbol - rangeCoder -> symbols;
ENET_RANGE_CODER_DECODE (root -> escapes + under, count, total);
root -> total += ENET_CONTEXT_SYMBOL_DELTA;
if (count > 0xFF - 2*ENET_CONTEXT_SYMBOL_DELTA + ENET_CONTEXT_SYMBOL_MINIMUM || root -> total > ENET_RANGE_CODER_BOTTOM - 0x100)
ENET_CONTEXT_RESCALE (root, ENET_CONTEXT_SYMBOL_MINIMUM);
patchContexts:
for (patch = & rangeCoder -> symbols [predicted];
patch != subcontext;
patch = & rangeCoder -> symbols [patch -> parent])
{
ENET_CONTEXT_ENCODE (patch, symbol, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0);
* parent = symbol - rangeCoder -> symbols;
parent = & symbol -> parent;
if (count <= 0)
{
patch -> escapes += ENET_SUBCONTEXT_ESCAPE_DELTA;
patch -> total += ENET_SUBCONTEXT_ESCAPE_DELTA;
}
patch -> total += ENET_SUBCONTEXT_SYMBOL_DELTA;
if (count > 0xFF - 2*ENET_SUBCONTEXT_SYMBOL_DELTA || patch -> total > ENET_RANGE_CODER_BOTTOM - 0x100)
ENET_CONTEXT_RESCALE (patch, 0);
}
* parent = bottom;
ENET_RANGE_CODER_OUTPUT (value);
if (order >= ENET_SUBCONTEXT_ORDER)
predicted = rangeCoder -> symbols [predicted].parent;
else
order ++;
ENET_RANGE_CODER_FREE_SYMBOLS;
}
return (size_t) (outData - outStart);
}
/** @defgroup host ENet host functions
@{
*/
/** Sets the packet compressor the host should use to the default range coder.
@param host host to enable the range coder for
@returns 0 on success, < 0 on failure
*/
int
enet_host_compress_with_range_coder (ENetHost * host)
{
ENetCompressor compressor;
memset (& compressor, 0, sizeof (compressor));
compressor.context = enet_range_coder_create();
if (compressor.context == NULL)
return -1;
compressor.compress = enet_range_coder_compress;
compressor.decompress = enet_range_coder_decompress;
compressor.destroy = enet_range_coder_destroy;
enet_host_compress (host, & compressor);
return 0;
}
/** @} */

503
vendor/enet/host.c vendored Normal file
View file

@ -0,0 +1,503 @@
/**
@file host.c
@brief ENet host management functions
*/
#define ENET_BUILDING_LIB 1
#include <string.h>
#include "enet/enet.h"
/** @defgroup host ENet host functions
@{
*/
/** Creates a host for communicating to peers.
@param address the address at which other peers may connect to this host. If NULL, then no peers may connect to the host.
@param peerCount the maximum number of peers that should be allocated for the host.
@param channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT
@param incomingBandwidth downstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth.
@param outgoingBandwidth upstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth.
@returns the host on success and NULL on failure
@remarks ENet will strategically drop packets on specific sides of a connection between hosts
to ensure the host's bandwidth is not overwhelmed. The bandwidth parameters also determine
the window size of a connection which limits the amount of reliable packets that may be in transit
at any given time.
*/
ENetHost *
enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelLimit, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
{
ENetHost * host;
ENetPeer * currentPeer;
if (peerCount > ENET_PROTOCOL_MAXIMUM_PEER_ID)
return NULL;
host = (ENetHost *) enet_malloc (sizeof (ENetHost));
if (host == NULL)
return NULL;
memset (host, 0, sizeof (ENetHost));
host -> peers = (ENetPeer *) enet_malloc (peerCount * sizeof (ENetPeer));
if (host -> peers == NULL)
{
enet_free (host);
return NULL;
}
memset (host -> peers, 0, peerCount * sizeof (ENetPeer));
host -> socket = enet_socket_create (ENET_SOCKET_TYPE_DATAGRAM);
if (host -> socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind (host -> socket, address) < 0))
{
if (host -> socket != ENET_SOCKET_NULL)
enet_socket_destroy (host -> socket);
enet_free (host -> peers);
enet_free (host);
return NULL;
}
enet_socket_set_option (host -> socket, ENET_SOCKOPT_NONBLOCK, 1);
enet_socket_set_option (host -> socket, ENET_SOCKOPT_BROADCAST, 1);
enet_socket_set_option (host -> socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE);
enet_socket_set_option (host -> socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE);
if (address != NULL && enet_socket_get_address (host -> socket, & host -> address) < 0)
host -> address = * address;
if (! channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
else
if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
host -> randomSeed = (enet_uint32) (size_t) host;
host -> randomSeed += enet_host_random_seed ();
host -> randomSeed = (host -> randomSeed << 16) | (host -> randomSeed >> 16);
host -> channelLimit = channelLimit;
host -> incomingBandwidth = incomingBandwidth;
host -> outgoingBandwidth = outgoingBandwidth;
host -> bandwidthThrottleEpoch = 0;
host -> recalculateBandwidthLimits = 0;
host -> mtu = ENET_HOST_DEFAULT_MTU;
host -> peerCount = peerCount;
host -> commandCount = 0;
host -> bufferCount = 0;
host -> checksum = NULL;
host -> receivedAddress.host = ENET_HOST_ANY;
host -> receivedAddress.port = 0;
host -> receivedData = NULL;
host -> receivedDataLength = 0;
host -> totalSentData = 0;
host -> totalSentPackets = 0;
host -> totalReceivedData = 0;
host -> totalReceivedPackets = 0;
host -> totalQueued = 0;
host -> connectedPeers = 0;
host -> bandwidthLimitedPeers = 0;
host -> duplicatePeers = ENET_PROTOCOL_MAXIMUM_PEER_ID;
host -> maximumPacketSize = ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE;
host -> maximumWaitingData = ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA;
host -> compressor.context = NULL;
host -> compressor.compress = NULL;
host -> compressor.decompress = NULL;
host -> compressor.destroy = NULL;
host -> intercept = NULL;
enet_list_clear (& host -> dispatchQueue);
for (currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
currentPeer -> host = host;
currentPeer -> incomingPeerID = currentPeer - host -> peers;
currentPeer -> outgoingSessionID = currentPeer -> incomingSessionID = 0xFF;
currentPeer -> data = NULL;
enet_list_clear (& currentPeer -> acknowledgements);
enet_list_clear (& currentPeer -> sentReliableCommands);
enet_list_clear (& currentPeer -> outgoingCommands);
enet_list_clear (& currentPeer -> outgoingSendReliableCommands);
enet_list_clear (& currentPeer -> dispatchedCommands);
enet_peer_reset (currentPeer);
}
return host;
}
/** Destroys the host and all resources associated with it.
@param host pointer to the host to destroy
*/
void
enet_host_destroy (ENetHost * host)
{
ENetPeer * currentPeer;
if (host == NULL)
return;
enet_socket_destroy (host -> socket);
for (currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
enet_peer_reset (currentPeer);
}
if (host -> compressor.context != NULL && host -> compressor.destroy)
(* host -> compressor.destroy) (host -> compressor.context);
enet_free (host -> peers);
enet_free (host);
}
enet_uint32
enet_host_random (ENetHost * host)
{
/* Mulberry32 by Tommy Ettinger */
enet_uint32 n = (host -> randomSeed += 0x6D2B79F5U);
n = (n ^ (n >> 15)) * (n | 1U);
n ^= n + (n ^ (n >> 7)) * (n | 61U);
return n ^ (n >> 14);
}
/** Initiates a connection to a foreign host.
@param host host seeking the connection
@param address destination for the connection
@param channelCount number of channels to allocate
@param data user data supplied to the receiving host
@returns a peer representing the foreign host on success, NULL on failure
@remarks The peer returned will have not completed the connection until enet_host_service()
notifies of an ENET_EVENT_TYPE_CONNECT event for the peer.
*/
ENetPeer *
enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelCount, enet_uint32 data)
{
ENetPeer * currentPeer;
ENetChannel * channel;
ENetProtocol command;
if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
channelCount = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
else
if (channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
channelCount = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
for (currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED)
break;
}
if (currentPeer >= & host -> peers [host -> peerCount])
return NULL;
currentPeer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel));
if (currentPeer -> channels == NULL)
return NULL;
currentPeer -> channelCount = channelCount;
currentPeer -> state = ENET_PEER_STATE_CONNECTING;
currentPeer -> address = * address;
currentPeer -> connectID = enet_host_random (host);
currentPeer -> mtu = host -> mtu;
if (host -> outgoingBandwidth == 0)
currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
else
currentPeer -> windowSize = (host -> outgoingBandwidth /
ENET_PEER_WINDOW_SIZE_SCALE) *
ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
if (currentPeer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
currentPeer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
else
if (currentPeer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
for (channel = currentPeer -> channels;
channel < & currentPeer -> channels [channelCount];
++ channel)
{
channel -> outgoingReliableSequenceNumber = 0;
channel -> outgoingUnreliableSequenceNumber = 0;
channel -> incomingReliableSequenceNumber = 0;
channel -> incomingUnreliableSequenceNumber = 0;
enet_list_clear (& channel -> incomingReliableCommands);
enet_list_clear (& channel -> incomingUnreliableCommands);
channel -> usedReliableWindows = 0;
memset (channel -> reliableWindows, 0, sizeof (channel -> reliableWindows));
}
command.header.command = ENET_PROTOCOL_COMMAND_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
command.header.channelID = 0xFF;
command.connect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID);
command.connect.incomingSessionID = currentPeer -> incomingSessionID;
command.connect.outgoingSessionID = currentPeer -> outgoingSessionID;
command.connect.mtu = ENET_HOST_TO_NET_32 (currentPeer -> mtu);
command.connect.windowSize = ENET_HOST_TO_NET_32 (currentPeer -> windowSize);
command.connect.channelCount = ENET_HOST_TO_NET_32 (channelCount);
command.connect.incomingBandwidth = ENET_HOST_TO_NET_32 (host -> incomingBandwidth);
command.connect.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
command.connect.packetThrottleInterval = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleInterval);
command.connect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleAcceleration);
command.connect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleDeceleration);
command.connect.connectID = currentPeer -> connectID;
command.connect.data = ENET_HOST_TO_NET_32 (data);
enet_peer_queue_outgoing_command (currentPeer, & command, NULL, 0, 0);
return currentPeer;
}
/** Queues a packet to be sent to all peers associated with the host.
@param host host on which to broadcast the packet
@param channelID channel on which to broadcast
@param packet packet to broadcast
*/
void
enet_host_broadcast (ENetHost * host, enet_uint8 channelID, ENetPacket * packet)
{
ENetPeer * currentPeer;
for (currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
if (currentPeer -> state != ENET_PEER_STATE_CONNECTED)
continue;
enet_peer_send (currentPeer, channelID, packet);
}
if (packet -> referenceCount == 0)
enet_packet_destroy (packet);
}
/** Sets the packet compressor the host should use to compress and decompress packets.
@param host host to enable or disable compression for
@param compressor callbacks for for the packet compressor; if NULL, then compression is disabled
*/
void
enet_host_compress (ENetHost * host, const ENetCompressor * compressor)
{
if (host -> compressor.context != NULL && host -> compressor.destroy)
(* host -> compressor.destroy) (host -> compressor.context);
if (compressor)
host -> compressor = * compressor;
else
host -> compressor.context = NULL;
}
/** Limits the maximum allowed channels of future incoming connections.
@param host host to limit
@param channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT
*/
void
enet_host_channel_limit (ENetHost * host, size_t channelLimit)
{
if (! channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
else
if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
host -> channelLimit = channelLimit;
}
/** Adjusts the bandwidth limits of a host.
@param host host to adjust
@param incomingBandwidth new incoming bandwidth
@param outgoingBandwidth new outgoing bandwidth
@remarks the incoming and outgoing bandwidth parameters are identical in function to those
specified in enet_host_create().
*/
void
enet_host_bandwidth_limit (ENetHost * host, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
{
host -> incomingBandwidth = incomingBandwidth;
host -> outgoingBandwidth = outgoingBandwidth;
host -> recalculateBandwidthLimits = 1;
}
void
enet_host_bandwidth_throttle (ENetHost * host)
{
enet_uint32 timeCurrent = enet_time_get (),
elapsedTime = timeCurrent - host -> bandwidthThrottleEpoch,
peersRemaining = (enet_uint32) host -> connectedPeers,
dataTotal = ~0,
bandwidth = ~0,
throttle = 0,
bandwidthLimit = 0;
int needsAdjustment = host -> bandwidthLimitedPeers > 0 ? 1 : 0;
ENetPeer * peer;
ENetProtocol command;
if (elapsedTime < ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL)
return;
host -> bandwidthThrottleEpoch = timeCurrent;
if (peersRemaining == 0)
return;
if (host -> outgoingBandwidth != 0)
{
dataTotal = 0;
bandwidth = (host -> outgoingBandwidth * elapsedTime) / 1000;
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
continue;
dataTotal += peer -> outgoingDataTotal;
}
}
while (peersRemaining > 0 && needsAdjustment != 0)
{
needsAdjustment = 0;
if (dataTotal <= bandwidth)
throttle = ENET_PEER_PACKET_THROTTLE_SCALE;
else
throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal;
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
enet_uint32 peerBandwidth;
if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
peer -> incomingBandwidth == 0 ||
peer -> outgoingBandwidthThrottleEpoch == timeCurrent)
continue;
peerBandwidth = (peer -> incomingBandwidth * elapsedTime) / 1000;
if ((throttle * peer -> outgoingDataTotal) / ENET_PEER_PACKET_THROTTLE_SCALE <= peerBandwidth)
continue;
peer -> packetThrottleLimit = (peerBandwidth *
ENET_PEER_PACKET_THROTTLE_SCALE) / peer -> outgoingDataTotal;
if (peer -> packetThrottleLimit == 0)
peer -> packetThrottleLimit = 1;
if (peer -> packetThrottle > peer -> packetThrottleLimit)
peer -> packetThrottle = peer -> packetThrottleLimit;
peer -> outgoingBandwidthThrottleEpoch = timeCurrent;
peer -> incomingDataTotal = 0;
peer -> outgoingDataTotal = 0;
needsAdjustment = 1;
-- peersRemaining;
bandwidth -= peerBandwidth;
dataTotal -= peerBandwidth;
}
}
if (peersRemaining > 0)
{
if (dataTotal <= bandwidth)
throttle = ENET_PEER_PACKET_THROTTLE_SCALE;
else
throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal;
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
peer -> outgoingBandwidthThrottleEpoch == timeCurrent)
continue;
peer -> packetThrottleLimit = throttle;
if (peer -> packetThrottle > peer -> packetThrottleLimit)
peer -> packetThrottle = peer -> packetThrottleLimit;
peer -> incomingDataTotal = 0;
peer -> outgoingDataTotal = 0;
}
}
if (host -> recalculateBandwidthLimits)
{
host -> recalculateBandwidthLimits = 0;
peersRemaining = (enet_uint32) host -> connectedPeers;
bandwidth = host -> incomingBandwidth;
needsAdjustment = 1;
if (bandwidth == 0)
bandwidthLimit = 0;
else
while (peersRemaining > 0 && needsAdjustment != 0)
{
needsAdjustment = 0;
bandwidthLimit = bandwidth / peersRemaining;
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
peer -> incomingBandwidthThrottleEpoch == timeCurrent)
continue;
if (peer -> outgoingBandwidth > 0 &&
peer -> outgoingBandwidth >= bandwidthLimit)
continue;
peer -> incomingBandwidthThrottleEpoch = timeCurrent;
needsAdjustment = 1;
-- peersRemaining;
bandwidth -= peer -> outgoingBandwidth;
}
}
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
continue;
command.header.command = ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
command.header.channelID = 0xFF;
command.bandwidthLimit.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
if (peer -> incomingBandwidthThrottleEpoch == timeCurrent)
command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32 (peer -> outgoingBandwidth);
else
command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32 (bandwidthLimit);
enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
}
}
}
/** @} */

37
vendor/enet/include/enet/callbacks.h vendored Normal file
View file

@ -0,0 +1,37 @@
/**
@file callbacks.h
@brief ENet callbacks
*/
#ifndef __ENET_CALLBACKS_H__
#define __ENET_CALLBACKS_H__
#include <stdlib.h>
typedef struct _ENetCallbacks
{
void * (ENET_CALLBACK * malloc) (size_t size);
void (ENET_CALLBACK * free) (void * memory);
void (ENET_CALLBACK * no_memory) (void);
} ENetCallbacks;
#ifdef __cplusplus
extern "C"
{
#endif
/** @defgroup callbacks ENet internal callbacks
@{
@ingroup private
*/
extern void * enet_malloc (size_t);
extern void enet_free (void *);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* __ENET_CALLBACKS_H__ */

615
vendor/enet/include/enet/enet.h vendored Normal file
View file

@ -0,0 +1,615 @@
/**
@file enet.h
@brief ENet public header file
*/
#ifndef __ENET_ENET_H__
#define __ENET_ENET_H__
#include <stdlib.h>
#ifdef _WIN32
#include "enet/win32.h"
#else
#include "enet/unix.h"
#endif
#include "enet/types.h"
#include "enet/protocol.h"
#include "enet/list.h"
#include "enet/callbacks.h"
#define ENET_VERSION_MAJOR 1
#define ENET_VERSION_MINOR 3
#define ENET_VERSION_PATCH 18
#define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch))
#define ENET_VERSION_GET_MAJOR(version) (((version)>>16)&0xFF)
#define ENET_VERSION_GET_MINOR(version) (((version)>>8)&0xFF)
#define ENET_VERSION_GET_PATCH(version) ((version)&0xFF)
#define ENET_VERSION ENET_VERSION_CREATE(ENET_VERSION_MAJOR, ENET_VERSION_MINOR, ENET_VERSION_PATCH)
typedef enet_uint32 ENetVersion;
struct _ENetHost;
struct _ENetEvent;
struct _ENetPacket;
typedef enum _ENetSocketType
{
ENET_SOCKET_TYPE_STREAM = 1,
ENET_SOCKET_TYPE_DATAGRAM = 2
} ENetSocketType;
typedef enum _ENetSocketWait
{
ENET_SOCKET_WAIT_NONE = 0,
ENET_SOCKET_WAIT_SEND = (1 << 0),
ENET_SOCKET_WAIT_RECEIVE = (1 << 1),
ENET_SOCKET_WAIT_INTERRUPT = (1 << 2)
} ENetSocketWait;
typedef enum _ENetSocketOption
{
ENET_SOCKOPT_NONBLOCK = 1,
ENET_SOCKOPT_BROADCAST = 2,
ENET_SOCKOPT_RCVBUF = 3,
ENET_SOCKOPT_SNDBUF = 4,
ENET_SOCKOPT_REUSEADDR = 5,
ENET_SOCKOPT_RCVTIMEO = 6,
ENET_SOCKOPT_SNDTIMEO = 7,
ENET_SOCKOPT_ERROR = 8,
ENET_SOCKOPT_NODELAY = 9,
ENET_SOCKOPT_TTL = 10
} ENetSocketOption;
typedef enum _ENetSocketShutdown
{
ENET_SOCKET_SHUTDOWN_READ = 0,
ENET_SOCKET_SHUTDOWN_WRITE = 1,
ENET_SOCKET_SHUTDOWN_READ_WRITE = 2
} ENetSocketShutdown;
#define ENET_HOST_ANY 0
#define ENET_HOST_BROADCAST 0xFFFFFFFFU
#define ENET_PORT_ANY 0
/**
* Portable internet address structure.
*
* The host must be specified in network byte-order, and the port must be in host
* byte-order. The constant ENET_HOST_ANY may be used to specify the default
* server host. The constant ENET_HOST_BROADCAST may be used to specify the
* broadcast address (255.255.255.255). This makes sense for enet_host_connect,
* but not for enet_host_create. Once a server responds to a broadcast, the
* address is updated from ENET_HOST_BROADCAST to the server's actual IP address.
*/
typedef struct _ENetAddress
{
enet_uint32 host;
enet_uint16 port;
} ENetAddress;
/**
* Packet flag bit constants.
*
* The host must be specified in network byte-order, and the port must be in
* host byte-order. The constant ENET_HOST_ANY may be used to specify the
* default server host.
@sa ENetPacket
*/
typedef enum _ENetPacketFlag
{
/** packet must be received by the target peer and resend attempts should be
* made until the packet is delivered */
ENET_PACKET_FLAG_RELIABLE = (1 << 0),
/** packet will not be sequenced with other packets
*/
ENET_PACKET_FLAG_UNSEQUENCED = (1 << 1),
/** packet will not allocate data, and user must supply it instead */
ENET_PACKET_FLAG_NO_ALLOCATE = (1 << 2),
/** packet will be fragmented using unreliable (instead of reliable) sends
* if it exceeds the MTU */
ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT = (1 << 3),
/** whether the packet has been sent from all queues it has been entered into */
ENET_PACKET_FLAG_SENT = (1<<8)
} ENetPacketFlag;
typedef void (ENET_CALLBACK * ENetPacketFreeCallback) (struct _ENetPacket *);
/**
* ENet packet structure.
*
* An ENet data packet that may be sent to or received from a peer. The shown
* fields should only be read and never modified. The data field contains the
* allocated data for the packet. The dataLength fields specifies the length
* of the allocated data. The flags field is either 0 (specifying no flags),
* or a bitwise-or of any combination of the following flags:
*
* ENET_PACKET_FLAG_RELIABLE - packet must be received by the target peer
* and resend attempts should be made until the packet is delivered
*
* ENET_PACKET_FLAG_UNSEQUENCED - packet will not be sequenced with other packets
* (not supported for reliable packets)
*
* ENET_PACKET_FLAG_NO_ALLOCATE - packet will not allocate data, and user must supply it instead
*
* ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT - packet will be fragmented using unreliable
* (instead of reliable) sends if it exceeds the MTU
*
* ENET_PACKET_FLAG_SENT - whether the packet has been sent from all queues it has been entered into
@sa ENetPacketFlag
*/
typedef struct _ENetPacket
{
size_t referenceCount; /**< internal use only */
enet_uint32 flags; /**< bitwise-or of ENetPacketFlag constants */
enet_uint8 * data; /**< allocated data for packet */
size_t dataLength; /**< length of data */
ENetPacketFreeCallback freeCallback; /**< function to be called when the packet is no longer in use */
void * userData; /**< application private data, may be freely modified */
} ENetPacket;
typedef struct _ENetAcknowledgement
{
ENetListNode acknowledgementList;
enet_uint32 sentTime;
ENetProtocol command;
} ENetAcknowledgement;
typedef struct _ENetOutgoingCommand
{
ENetListNode outgoingCommandList;
enet_uint16 reliableSequenceNumber;
enet_uint16 unreliableSequenceNumber;
enet_uint32 sentTime;
enet_uint32 roundTripTimeout;
enet_uint32 queueTime;
enet_uint32 fragmentOffset;
enet_uint16 fragmentLength;
enet_uint16 sendAttempts;
ENetProtocol command;
ENetPacket * packet;
} ENetOutgoingCommand;
typedef struct _ENetIncomingCommand
{
ENetListNode incomingCommandList;
enet_uint16 reliableSequenceNumber;
enet_uint16 unreliableSequenceNumber;
ENetProtocol command;
enet_uint32 fragmentCount;
enet_uint32 fragmentsRemaining;
enet_uint32 * fragments;
ENetPacket * packet;
} ENetIncomingCommand;
typedef enum _ENetPeerState
{
ENET_PEER_STATE_DISCONNECTED = 0,
ENET_PEER_STATE_CONNECTING = 1,
ENET_PEER_STATE_ACKNOWLEDGING_CONNECT = 2,
ENET_PEER_STATE_CONNECTION_PENDING = 3,
ENET_PEER_STATE_CONNECTION_SUCCEEDED = 4,
ENET_PEER_STATE_CONNECTED = 5,
ENET_PEER_STATE_DISCONNECT_LATER = 6,
ENET_PEER_STATE_DISCONNECTING = 7,
ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT = 8,
ENET_PEER_STATE_ZOMBIE = 9
} ENetPeerState;
#ifndef ENET_BUFFER_MAXIMUM
#define ENET_BUFFER_MAXIMUM (1 + 2 * ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS)
#endif
enum
{
ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024,
ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024,
ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000,
ENET_HOST_DEFAULT_MTU = 1392,
ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024,
ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024,
ENET_PEER_DEFAULT_ROUND_TRIP_TIME = 500,
ENET_PEER_DEFAULT_PACKET_THROTTLE = 32,
ENET_PEER_PACKET_THROTTLE_SCALE = 32,
ENET_PEER_PACKET_THROTTLE_COUNTER = 7,
ENET_PEER_PACKET_THROTTLE_ACCELERATION = 2,
ENET_PEER_PACKET_THROTTLE_DECELERATION = 2,
ENET_PEER_PACKET_THROTTLE_INTERVAL = 5000,
ENET_PEER_PACKET_LOSS_SCALE = (1 << 16),
ENET_PEER_PACKET_LOSS_INTERVAL = 10000,
ENET_PEER_WINDOW_SIZE_SCALE = 64 * 1024,
ENET_PEER_TIMEOUT_LIMIT = 32,
ENET_PEER_TIMEOUT_MINIMUM = 5000,
ENET_PEER_TIMEOUT_MAXIMUM = 30000,
ENET_PEER_PING_INTERVAL = 500,
ENET_PEER_UNSEQUENCED_WINDOWS = 64,
ENET_PEER_UNSEQUENCED_WINDOW_SIZE = 1024,
ENET_PEER_FREE_UNSEQUENCED_WINDOWS = 32,
ENET_PEER_RELIABLE_WINDOWS = 16,
ENET_PEER_RELIABLE_WINDOW_SIZE = 0x1000,
ENET_PEER_FREE_RELIABLE_WINDOWS = 8
};
typedef struct _ENetChannel
{
enet_uint16 outgoingReliableSequenceNumber;
enet_uint16 outgoingUnreliableSequenceNumber;
enet_uint16 usedReliableWindows;
enet_uint16 reliableWindows [ENET_PEER_RELIABLE_WINDOWS];
enet_uint16 incomingReliableSequenceNumber;
enet_uint16 incomingUnreliableSequenceNumber;
ENetList incomingReliableCommands;
ENetList incomingUnreliableCommands;
} ENetChannel;
typedef enum _ENetPeerFlag
{
ENET_PEER_FLAG_NEEDS_DISPATCH = (1 << 0),
ENET_PEER_FLAG_CONTINUE_SENDING = (1 << 1)
} ENetPeerFlag;
/**
* An ENet peer which data packets may be sent or received from.
*
* No fields should be modified unless otherwise specified.
*/
typedef struct _ENetPeer
{
ENetListNode dispatchList;
struct _ENetHost * host;
enet_uint16 outgoingPeerID;
enet_uint16 incomingPeerID;
enet_uint32 connectID;
enet_uint8 outgoingSessionID;
enet_uint8 incomingSessionID;
ENetAddress address; /**< Internet address of the peer */
void * data; /**< Application private data, may be freely modified */
ENetPeerState state;
ENetChannel * channels;
size_t channelCount; /**< Number of channels allocated for communication with peer */
enet_uint32 incomingBandwidth; /**< Downstream bandwidth of the client in bytes/second */
enet_uint32 outgoingBandwidth; /**< Upstream bandwidth of the client in bytes/second */
enet_uint32 incomingBandwidthThrottleEpoch;
enet_uint32 outgoingBandwidthThrottleEpoch;
enet_uint32 incomingDataTotal;
enet_uint32 outgoingDataTotal;
enet_uint32 lastSendTime;
enet_uint32 lastReceiveTime;
enet_uint32 nextTimeout;
enet_uint32 earliestTimeout;
enet_uint32 packetLossEpoch;
enet_uint32 packetsSent;
enet_uint32 packetsLost;
enet_uint32 packetLoss; /**< mean packet loss of reliable packets as a ratio with respect to the constant ENET_PEER_PACKET_LOSS_SCALE */
enet_uint32 packetLossVariance;
enet_uint32 packetThrottle;
enet_uint32 packetThrottleLimit;
enet_uint32 packetThrottleCounter;
enet_uint32 packetThrottleEpoch;
enet_uint32 packetThrottleAcceleration;
enet_uint32 packetThrottleDeceleration;
enet_uint32 packetThrottleInterval;
enet_uint32 pingInterval;
enet_uint32 timeoutLimit;
enet_uint32 timeoutMinimum;
enet_uint32 timeoutMaximum;
enet_uint32 lastRoundTripTime;
enet_uint32 lowestRoundTripTime;
enet_uint32 lastRoundTripTimeVariance;
enet_uint32 highestRoundTripTimeVariance;
enet_uint32 roundTripTime; /**< mean round trip time (RTT), in milliseconds, between sending a reliable packet and receiving its acknowledgement */
enet_uint32 roundTripTimeVariance;
enet_uint32 mtu;
enet_uint32 windowSize;
enet_uint32 reliableDataInTransit;
enet_uint16 outgoingReliableSequenceNumber;
ENetList acknowledgements;
ENetList sentReliableCommands;
ENetList outgoingSendReliableCommands;
ENetList outgoingCommands;
ENetList dispatchedCommands;
enet_uint16 flags;
enet_uint16 reserved;
enet_uint16 incomingUnsequencedGroup;
enet_uint16 outgoingUnsequencedGroup;
enet_uint32 unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32];
enet_uint32 eventData;
size_t totalWaitingData;
} ENetPeer;
/** An ENet packet compressor for compressing UDP packets before socket sends or receives.
*/
typedef struct _ENetCompressor
{
/** Context data for the compressor. Must be non-NULL. */
void * context;
/** Compresses from inBuffers[0:inBufferCount-1], containing inLimit bytes, to outData, outputting at most outLimit bytes. Should return 0 on failure. */
size_t (ENET_CALLBACK * compress) (void * context, const ENetBuffer * inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 * outData, size_t outLimit);
/** Decompresses from inData, containing inLimit bytes, to outData, outputting at most outLimit bytes. Should return 0 on failure. */
size_t (ENET_CALLBACK * decompress) (void * context, const enet_uint8 * inData, size_t inLimit, enet_uint8 * outData, size_t outLimit);
/** Destroys the context when compression is disabled or the host is destroyed. May be NULL. */
void (ENET_CALLBACK * destroy) (void * context);
} ENetCompressor;
/** Callback that computes the checksum of the data held in buffers[0:bufferCount-1] */
typedef enet_uint32 (ENET_CALLBACK * ENetChecksumCallback) (const ENetBuffer * buffers, size_t bufferCount);
/** Callback for intercepting received raw UDP packets. Should return 1 to intercept, 0 to ignore, or -1 to propagate an error. */
typedef int (ENET_CALLBACK * ENetInterceptCallback) (struct _ENetHost * host, struct _ENetEvent * event);
/** An ENet host for communicating with peers.
*
* No fields should be modified unless otherwise stated.
@sa enet_host_create()
@sa enet_host_destroy()
@sa enet_host_connect()
@sa enet_host_service()
@sa enet_host_flush()
@sa enet_host_broadcast()
@sa enet_host_compress()
@sa enet_host_compress_with_range_coder()
@sa enet_host_channel_limit()
@sa enet_host_bandwidth_limit()
@sa enet_host_bandwidth_throttle()
*/
typedef struct _ENetHost
{
ENetSocket socket;
ENetAddress address; /**< Internet address of the host */
enet_uint32 incomingBandwidth; /**< downstream bandwidth of the host */
enet_uint32 outgoingBandwidth; /**< upstream bandwidth of the host */
enet_uint32 bandwidthThrottleEpoch;
enet_uint32 mtu;
enet_uint32 randomSeed;
int recalculateBandwidthLimits;
ENetPeer * peers; /**< array of peers allocated for this host */
size_t peerCount; /**< number of peers allocated for this host */
size_t channelLimit; /**< maximum number of channels allowed for connected peers */
enet_uint32 serviceTime;
ENetList dispatchQueue;
enet_uint32 totalQueued;
size_t packetSize;
enet_uint16 headerFlags;
ENetProtocol commands [ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS];
size_t commandCount;
ENetBuffer buffers [ENET_BUFFER_MAXIMUM];
size_t bufferCount;
ENetChecksumCallback checksum; /**< callback the user can set to enable packet checksums for this host */
ENetCompressor compressor;
enet_uint8 packetData [2][ENET_PROTOCOL_MAXIMUM_MTU];
ENetAddress receivedAddress;
enet_uint8 * receivedData;
size_t receivedDataLength;
enet_uint32 totalSentData; /**< total data sent, user should reset to 0 as needed to prevent overflow */
enet_uint32 totalSentPackets; /**< total UDP packets sent, user should reset to 0 as needed to prevent overflow */
enet_uint32 totalReceivedData; /**< total data received, user should reset to 0 as needed to prevent overflow */
enet_uint32 totalReceivedPackets; /**< total UDP packets received, user should reset to 0 as needed to prevent overflow */
ENetInterceptCallback intercept; /**< callback the user can set to intercept received raw UDP packets */
size_t connectedPeers;
size_t bandwidthLimitedPeers;
size_t duplicatePeers; /**< optional number of allowed peers from duplicate IPs, defaults to ENET_PROTOCOL_MAXIMUM_PEER_ID */
size_t maximumPacketSize; /**< the maximum allowable packet size that may be sent or received on a peer */
size_t maximumWaitingData; /**< the maximum aggregate amount of buffer space a peer may use waiting for packets to be delivered */
} ENetHost;
/**
* An ENet event type, as specified in @ref ENetEvent.
*/
typedef enum _ENetEventType
{
/** no event occurred within the specified time limit */
ENET_EVENT_TYPE_NONE = 0,
/** a connection request initiated by enet_host_connect has completed.
* The peer field contains the peer which successfully connected.
*/
ENET_EVENT_TYPE_CONNECT = 1,
/** a peer has disconnected. This event is generated on a successful
* completion of a disconnect initiated by enet_peer_disconnect, if
* a peer has timed out, or if a connection request intialized by
* enet_host_connect has timed out. The peer field contains the peer
* which disconnected. The data field contains user supplied data
* describing the disconnection, or 0, if none is available.
*/
ENET_EVENT_TYPE_DISCONNECT = 2,
/** a packet has been received from a peer. The peer field specifies the
* peer which sent the packet. The channelID field specifies the channel
* number upon which the packet was received. The packet field contains
* the packet that was received; this packet must be destroyed with
* enet_packet_destroy after use.
*/
ENET_EVENT_TYPE_RECEIVE = 3
} ENetEventType;
/**
* An ENet event as returned by enet_host_service().
@sa enet_host_service
*/
typedef struct _ENetEvent
{
ENetEventType type; /**< type of the event */
ENetPeer * peer; /**< peer that generated a connect, disconnect or receive event */
enet_uint8 channelID; /**< channel on the peer that generated the event, if appropriate */
enet_uint32 data; /**< data associated with the event, if appropriate */
ENetPacket * packet; /**< packet associated with the event, if appropriate */
} ENetEvent;
#ifdef __cplusplus
extern "C"
{
#endif
/** @defgroup global ENet global functions
@{
*/
/**
Initializes ENet globally. Must be called prior to using any functions in
ENet.
@returns 0 on success, < 0 on failure
*/
ENET_API int enet_initialize (void);
/**
Initializes ENet globally and supplies user-overridden callbacks. Must be called prior to using any functions in ENet. Do not use enet_initialize() if you use this variant. Make sure the ENetCallbacks structure is zeroed out so that any additional callbacks added in future versions will be properly ignored.
@param version the constant ENET_VERSION should be supplied so ENet knows which version of ENetCallbacks struct to use
@param inits user-overridden callbacks where any NULL callbacks will use ENet's defaults
@returns 0 on success, < 0 on failure
*/
ENET_API int enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits);
/**
Shuts down ENet globally. Should be called when a program that has
initialized ENet exits.
*/
ENET_API void enet_deinitialize (void);
/**
Gives the linked version of the ENet library.
@returns the version number
*/
ENET_API ENetVersion enet_linked_version (void);
/** @} */
/** @defgroup private ENet private implementation functions */
/**
Returns the wall-time in milliseconds. Its initial value is unspecified
unless otherwise set.
*/
ENET_API enet_uint32 enet_time_get (void);
/**
Sets the current wall-time in milliseconds.
*/
ENET_API void enet_time_set (enet_uint32);
/** @defgroup socket ENet socket functions
@{
*/
ENET_API ENetSocket enet_socket_create (ENetSocketType);
ENET_API int enet_socket_bind (ENetSocket, const ENetAddress *);
ENET_API int enet_socket_get_address (ENetSocket, ENetAddress *);
ENET_API int enet_socket_listen (ENetSocket, int);
ENET_API ENetSocket enet_socket_accept (ENetSocket, ENetAddress *);
ENET_API int enet_socket_connect (ENetSocket, const ENetAddress *);
ENET_API int enet_socket_send (ENetSocket, const ENetAddress *, const ENetBuffer *, size_t);
ENET_API int enet_socket_receive (ENetSocket, ENetAddress *, ENetBuffer *, size_t);
ENET_API int enet_socket_wait (ENetSocket, enet_uint32 *, enet_uint32);
ENET_API int enet_socket_set_option (ENetSocket, ENetSocketOption, int);
ENET_API int enet_socket_get_option (ENetSocket, ENetSocketOption, int *);
ENET_API int enet_socket_shutdown (ENetSocket, ENetSocketShutdown);
ENET_API void enet_socket_destroy (ENetSocket);
ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSocketSet *, enet_uint32);
/** @} */
/** @defgroup Address ENet address functions
@{
*/
/** Attempts to parse the printable form of the IP address in the parameter hostName
and sets the host field in the address parameter if successful.
@param address destination to store the parsed IP address
@param hostName IP address to parse
@retval 0 on success
@retval < 0 on failure
@returns the address of the given hostName in address on success
*/
ENET_API int enet_address_set_host_ip (ENetAddress * address, const char * hostName);
/** Attempts to resolve the host named by the parameter hostName and sets
the host field in the address parameter if successful.
@param address destination to store resolved address
@param hostName host name to lookup
@retval 0 on success
@retval < 0 on failure
@returns the address of the given hostName in address on success
*/
ENET_API int enet_address_set_host (ENetAddress * address, const char * hostName);
/** Gives the printable form of the IP address specified in the address parameter.
@param address address printed
@param hostName destination for name, must not be NULL
@param nameLength maximum length of hostName.
@returns the null-terminated name of the host in hostName on success
@retval 0 on success
@retval < 0 on failure
*/
ENET_API int enet_address_get_host_ip (const ENetAddress * address, char * hostName, size_t nameLength);
/** Attempts to do a reverse lookup of the host field in the address parameter.
@param address address used for reverse lookup
@param hostName destination for name, must not be NULL
@param nameLength maximum length of hostName.
@returns the null-terminated name of the host in hostName on success
@retval 0 on success
@retval < 0 on failure
*/
ENET_API int enet_address_get_host (const ENetAddress * address, char * hostName, size_t nameLength);
/** @} */
ENET_API ENetPacket * enet_packet_create (const void *, size_t, enet_uint32);
ENET_API void enet_packet_destroy (ENetPacket *);
ENET_API int enet_packet_resize (ENetPacket *, size_t);
ENET_API enet_uint32 enet_crc32 (const ENetBuffer *, size_t);
ENET_API ENetHost * enet_host_create (const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32);
ENET_API void enet_host_destroy (ENetHost *);
ENET_API ENetPeer * enet_host_connect (ENetHost *, const ENetAddress *, size_t, enet_uint32);
ENET_API int enet_host_check_events (ENetHost *, ENetEvent *);
ENET_API int enet_host_service (ENetHost *, ENetEvent *, enet_uint32);
ENET_API void enet_host_flush (ENetHost *);
ENET_API void enet_host_broadcast (ENetHost *, enet_uint8, ENetPacket *);
ENET_API void enet_host_compress (ENetHost *, const ENetCompressor *);
ENET_API int enet_host_compress_with_range_coder (ENetHost * host);
ENET_API void enet_host_channel_limit (ENetHost *, size_t);
ENET_API void enet_host_bandwidth_limit (ENetHost *, enet_uint32, enet_uint32);
extern void enet_host_bandwidth_throttle (ENetHost *);
extern enet_uint32 enet_host_random_seed (void);
extern enet_uint32 enet_host_random (ENetHost *);
ENET_API int enet_peer_send (ENetPeer *, enet_uint8, ENetPacket *);
ENET_API ENetPacket * enet_peer_receive (ENetPeer *, enet_uint8 * channelID);
ENET_API void enet_peer_ping (ENetPeer *);
ENET_API void enet_peer_ping_interval (ENetPeer *, enet_uint32);
ENET_API void enet_peer_timeout (ENetPeer *, enet_uint32, enet_uint32, enet_uint32);
ENET_API void enet_peer_reset (ENetPeer *);
ENET_API void enet_peer_disconnect (ENetPeer *, enet_uint32);
ENET_API void enet_peer_disconnect_now (ENetPeer *, enet_uint32);
ENET_API void enet_peer_disconnect_later (ENetPeer *, enet_uint32);
ENET_API void enet_peer_throttle_configure (ENetPeer *, enet_uint32, enet_uint32, enet_uint32);
extern int enet_peer_throttle (ENetPeer *, enet_uint32);
extern void enet_peer_reset_queues (ENetPeer *);
extern int enet_peer_has_outgoing_commands (ENetPeer *);
extern void enet_peer_setup_outgoing_command (ENetPeer *, ENetOutgoingCommand *);
extern ENetOutgoingCommand * enet_peer_queue_outgoing_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32, enet_uint16);
extern ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const ENetProtocol *, const void *, size_t, enet_uint32, enet_uint32);
extern ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer *, const ENetProtocol *, enet_uint16);
extern void enet_peer_dispatch_incoming_unreliable_commands (ENetPeer *, ENetChannel *, ENetIncomingCommand *);
extern void enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *, ENetIncomingCommand *);
extern void enet_peer_on_connect (ENetPeer *);
extern void enet_peer_on_disconnect (ENetPeer *);
ENET_API void * enet_range_coder_create (void);
ENET_API void enet_range_coder_destroy (void *);
ENET_API size_t enet_range_coder_compress (void *, const ENetBuffer *, size_t, size_t, enet_uint8 *, size_t);
ENET_API size_t enet_range_coder_decompress (void *, const enet_uint8 *, size_t, enet_uint8 *, size_t);
extern size_t enet_protocol_command_size (enet_uint8);
#ifdef __cplusplus
}
#endif
#endif /* __ENET_ENET_H__ */

52
vendor/enet/include/enet/list.h vendored Normal file
View file

@ -0,0 +1,52 @@
/**
@file list.h
@brief ENet list management
*/
#ifndef __ENET_LIST_H__
#define __ENET_LIST_H__
#include <stdlib.h>
typedef struct _ENetListNode
{
struct _ENetListNode * next;
struct _ENetListNode * previous;
} ENetListNode;
typedef ENetListNode * ENetListIterator;
typedef struct _ENetList
{
ENetListNode sentinel;
} ENetList;
#ifdef __cplusplus
extern "C"
{
#endif
extern void enet_list_clear (ENetList *);
extern ENetListIterator enet_list_insert (ENetListIterator, void *);
extern void * enet_list_remove (ENetListIterator);
extern ENetListIterator enet_list_move (ENetListIterator, void *, void *);
extern size_t enet_list_size (ENetList *);
#ifdef __cplusplus
}
#endif
#define enet_list_begin(list) ((list) -> sentinel.next)
#define enet_list_end(list) (& (list) -> sentinel)
#define enet_list_empty(list) (enet_list_begin (list) == enet_list_end (list))
#define enet_list_next(iterator) ((iterator) -> next)
#define enet_list_previous(iterator) ((iterator) -> previous)
#define enet_list_front(list) ((void *) (list) -> sentinel.next)
#define enet_list_back(list) ((void *) (list) -> sentinel.previous)
#endif /* __ENET_LIST_H__ */

198
vendor/enet/include/enet/protocol.h vendored Normal file
View file

@ -0,0 +1,198 @@
/**
@file protocol.h
@brief ENet protocol
*/
#ifndef __ENET_PROTOCOL_H__
#define __ENET_PROTOCOL_H__
#include "enet/types.h"
enum
{
ENET_PROTOCOL_MINIMUM_MTU = 576,
ENET_PROTOCOL_MAXIMUM_MTU = 4096,
ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS = 32,
ENET_PROTOCOL_MINIMUM_WINDOW_SIZE = 4096,
ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 65536,
ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT = 1,
ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 255,
ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFF,
ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT = 1024 * 1024
};
typedef enum _ENetProtocolCommand
{
ENET_PROTOCOL_COMMAND_NONE = 0,
ENET_PROTOCOL_COMMAND_ACKNOWLEDGE = 1,
ENET_PROTOCOL_COMMAND_CONNECT = 2,
ENET_PROTOCOL_COMMAND_VERIFY_CONNECT = 3,
ENET_PROTOCOL_COMMAND_DISCONNECT = 4,
ENET_PROTOCOL_COMMAND_PING = 5,
ENET_PROTOCOL_COMMAND_SEND_RELIABLE = 6,
ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE = 7,
ENET_PROTOCOL_COMMAND_SEND_FRAGMENT = 8,
ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED = 9,
ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT = 10,
ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE = 11,
ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT = 12,
ENET_PROTOCOL_COMMAND_COUNT = 13,
ENET_PROTOCOL_COMMAND_MASK = 0x0F
} ENetProtocolCommand;
typedef enum _ENetProtocolFlag
{
ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE = (1 << 7),
ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED = (1 << 6),
ENET_PROTOCOL_HEADER_FLAG_COMPRESSED = (1 << 14),
ENET_PROTOCOL_HEADER_FLAG_SENT_TIME = (1 << 15),
ENET_PROTOCOL_HEADER_FLAG_MASK = ENET_PROTOCOL_HEADER_FLAG_COMPRESSED | ENET_PROTOCOL_HEADER_FLAG_SENT_TIME,
ENET_PROTOCOL_HEADER_SESSION_MASK = (3 << 12),
ENET_PROTOCOL_HEADER_SESSION_SHIFT = 12
} ENetProtocolFlag;
#ifdef _MSC_VER
#pragma pack(push, 1)
#define ENET_PACKED
#elif defined(__GNUC__) || defined(__clang__)
#define ENET_PACKED __attribute__ ((packed))
#else
#define ENET_PACKED
#endif
typedef struct _ENetProtocolHeader
{
enet_uint16 peerID;
enet_uint16 sentTime;
} ENET_PACKED ENetProtocolHeader;
typedef struct _ENetProtocolCommandHeader
{
enet_uint8 command;
enet_uint8 channelID;
enet_uint16 reliableSequenceNumber;
} ENET_PACKED ENetProtocolCommandHeader;
typedef struct _ENetProtocolAcknowledge
{
ENetProtocolCommandHeader header;
enet_uint16 receivedReliableSequenceNumber;
enet_uint16 receivedSentTime;
} ENET_PACKED ENetProtocolAcknowledge;
typedef struct _ENetProtocolConnect
{
ENetProtocolCommandHeader header;
enet_uint16 outgoingPeerID;
enet_uint8 incomingSessionID;
enet_uint8 outgoingSessionID;
enet_uint32 mtu;
enet_uint32 windowSize;
enet_uint32 channelCount;
enet_uint32 incomingBandwidth;
enet_uint32 outgoingBandwidth;
enet_uint32 packetThrottleInterval;
enet_uint32 packetThrottleAcceleration;
enet_uint32 packetThrottleDeceleration;
enet_uint32 connectID;
enet_uint32 data;
} ENET_PACKED ENetProtocolConnect;
typedef struct _ENetProtocolVerifyConnect
{
ENetProtocolCommandHeader header;
enet_uint16 outgoingPeerID;
enet_uint8 incomingSessionID;
enet_uint8 outgoingSessionID;
enet_uint32 mtu;
enet_uint32 windowSize;
enet_uint32 channelCount;
enet_uint32 incomingBandwidth;
enet_uint32 outgoingBandwidth;
enet_uint32 packetThrottleInterval;
enet_uint32 packetThrottleAcceleration;
enet_uint32 packetThrottleDeceleration;
enet_uint32 connectID;
} ENET_PACKED ENetProtocolVerifyConnect;
typedef struct _ENetProtocolBandwidthLimit
{
ENetProtocolCommandHeader header;
enet_uint32 incomingBandwidth;
enet_uint32 outgoingBandwidth;
} ENET_PACKED ENetProtocolBandwidthLimit;
typedef struct _ENetProtocolThrottleConfigure
{
ENetProtocolCommandHeader header;
enet_uint32 packetThrottleInterval;
enet_uint32 packetThrottleAcceleration;
enet_uint32 packetThrottleDeceleration;
} ENET_PACKED ENetProtocolThrottleConfigure;
typedef struct _ENetProtocolDisconnect
{
ENetProtocolCommandHeader header;
enet_uint32 data;
} ENET_PACKED ENetProtocolDisconnect;
typedef struct _ENetProtocolPing
{
ENetProtocolCommandHeader header;
} ENET_PACKED ENetProtocolPing;
typedef struct _ENetProtocolSendReliable
{
ENetProtocolCommandHeader header;
enet_uint16 dataLength;
} ENET_PACKED ENetProtocolSendReliable;
typedef struct _ENetProtocolSendUnreliable
{
ENetProtocolCommandHeader header;
enet_uint16 unreliableSequenceNumber;
enet_uint16 dataLength;
} ENET_PACKED ENetProtocolSendUnreliable;
typedef struct _ENetProtocolSendUnsequenced
{
ENetProtocolCommandHeader header;
enet_uint16 unsequencedGroup;
enet_uint16 dataLength;
} ENET_PACKED ENetProtocolSendUnsequenced;
typedef struct _ENetProtocolSendFragment
{
ENetProtocolCommandHeader header;
enet_uint16 startSequenceNumber;
enet_uint16 dataLength;
enet_uint32 fragmentCount;
enet_uint32 fragmentNumber;
enet_uint32 totalLength;
enet_uint32 fragmentOffset;
} ENET_PACKED ENetProtocolSendFragment;
typedef union _ENetProtocol
{
ENetProtocolCommandHeader header;
ENetProtocolAcknowledge acknowledge;
ENetProtocolConnect connect;
ENetProtocolVerifyConnect verifyConnect;
ENetProtocolDisconnect disconnect;
ENetProtocolPing ping;
ENetProtocolSendReliable sendReliable;
ENetProtocolSendUnreliable sendUnreliable;
ENetProtocolSendUnsequenced sendUnsequenced;
ENetProtocolSendFragment sendFragment;
ENetProtocolBandwidthLimit bandwidthLimit;
ENetProtocolThrottleConfigure throttleConfigure;
} ENET_PACKED ENetProtocol;
#ifdef _MSC_VER
#pragma pack(pop)
#endif
#endif /* __ENET_PROTOCOL_H__ */

18
vendor/enet/include/enet/time.h vendored Normal file
View file

@ -0,0 +1,18 @@
/**
@file time.h
@brief ENet time constants and macros
*/
#ifndef __ENET_TIME_H__
#define __ENET_TIME_H__
#define ENET_TIME_OVERFLOW 86400000
#define ENET_TIME_LESS(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW)
#define ENET_TIME_GREATER(a, b) ((b) - (a) >= ENET_TIME_OVERFLOW)
#define ENET_TIME_LESS_EQUAL(a, b) (! ENET_TIME_GREATER (a, b))
#define ENET_TIME_GREATER_EQUAL(a, b) (! ENET_TIME_LESS (a, b))
#define ENET_TIME_DIFFERENCE(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW ? (b) - (a) : (a) - (b))
#endif /* __ENET_TIME_H__ */

13
vendor/enet/include/enet/types.h vendored Normal file
View file

@ -0,0 +1,13 @@
/**
@file types.h
@brief type definitions for ENet
*/
#ifndef __ENET_TYPES_H__
#define __ENET_TYPES_H__
typedef unsigned char enet_uint8; /**< unsigned 8-bit type */
typedef unsigned short enet_uint16; /**< unsigned 16-bit type */
typedef unsigned int enet_uint32; /**< unsigned 32-bit type */
#endif /* __ENET_TYPES_H__ */

48
vendor/enet/include/enet/unix.h vendored Normal file
View file

@ -0,0 +1,48 @@
/**
@file unix.h
@brief ENet Unix header
*/
#ifndef __ENET_UNIX_H__
#define __ENET_UNIX_H__
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#ifdef MSG_MAXIOVLEN
#define ENET_BUFFER_MAXIMUM MSG_MAXIOVLEN
#endif
typedef int ENetSocket;
#define ENET_SOCKET_NULL -1
#define ENET_HOST_TO_NET_16(value) (htons (value)) /**< macro that converts host to net byte-order of a 16-bit value */
#define ENET_HOST_TO_NET_32(value) (htonl (value)) /**< macro that converts host to net byte-order of a 32-bit value */
#define ENET_NET_TO_HOST_16(value) (ntohs (value)) /**< macro that converts net to host byte-order of a 16-bit value */
#define ENET_NET_TO_HOST_32(value) (ntohl (value)) /**< macro that converts net to host byte-order of a 32-bit value */
typedef struct
{
void * data;
size_t dataLength;
} ENetBuffer;
#define ENET_CALLBACK
#define ENET_API extern
typedef fd_set ENetSocketSet;
#define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset))
#define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset))
#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset))
#define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset))
#endif /* __ENET_UNIX_H__ */

23
vendor/enet/include/enet/utility.h vendored Normal file
View file

@ -0,0 +1,23 @@
/**
@file utility.h
@brief ENet utility header
*/
#ifndef __ENET_UTILITY_H__
#define __ENET_UTILITY_H__
#ifdef HAS_OFFSETOF
#include <stddef.h>
#endif
#define ENET_MAX(x, y) ((x) > (y) ? (x) : (y))
#define ENET_MIN(x, y) ((x) < (y) ? (x) : (y))
#define ENET_DIFFERENCE(x, y) ((x) < (y) ? (y) - (x) : (x) - (y))
#ifdef HAS_OFFSETOF
#define ENET_OFFSETOF(str, field) (offsetof(str, field))
#else
#define ENET_OFFSETOF(str, field) ((size_t) & ((str *) 0) -> field)
#endif
#endif /* __ENET_UTILITY_H__ */

63
vendor/enet/include/enet/win32.h vendored Normal file
View file

@ -0,0 +1,63 @@
/**
@file win32.h
@brief ENet Win32 header
*/
#ifndef __ENET_WIN32_H__
#define __ENET_WIN32_H__
#ifdef _MSC_VER
#ifdef ENET_BUILDING_LIB
#pragma warning (disable: 4267) // size_t to int conversion
#pragma warning (disable: 4244) // 64bit to 32bit int
#pragma warning (disable: 4018) // signed/unsigned mismatch
#pragma warning (disable: 4146) // unary minus operator applied to unsigned type
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE
#endif
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#endif
#endif
#include <stdlib.h>
#include <winsock2.h>
typedef SOCKET ENetSocket;
#define ENET_SOCKET_NULL INVALID_SOCKET
#define ENET_HOST_TO_NET_16(value) (htons (value))
#define ENET_HOST_TO_NET_32(value) (htonl (value))
#define ENET_NET_TO_HOST_16(value) (ntohs (value))
#define ENET_NET_TO_HOST_32(value) (ntohl (value))
typedef struct
{
size_t dataLength;
void * data;
} ENetBuffer;
#define ENET_CALLBACK __cdecl
#ifdef ENET_DLL
#ifdef ENET_BUILDING_LIB
#define ENET_API __declspec( dllexport )
#else
#define ENET_API __declspec( dllimport )
#endif /* ENET_BUILDING_LIB */
#else /* !ENET_DLL */
#define ENET_API extern
#endif /* ENET_DLL */
typedef fd_set ENetSocketSet;
#define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset))
#define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset))
#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset))
#define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset))
#endif /* __ENET_WIN32_H__ */

75
vendor/enet/list.c vendored Normal file
View file

@ -0,0 +1,75 @@
/**
@file list.c
@brief ENet linked list functions
*/
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
/**
@defgroup list ENet linked list utility functions
@ingroup private
@{
*/
void
enet_list_clear (ENetList * list)
{
list -> sentinel.next = & list -> sentinel;
list -> sentinel.previous = & list -> sentinel;
}
ENetListIterator
enet_list_insert (ENetListIterator position, void * data)
{
ENetListIterator result = (ENetListIterator) data;
result -> previous = position -> previous;
result -> next = position;
result -> previous -> next = result;
position -> previous = result;
return result;
}
void *
enet_list_remove (ENetListIterator position)
{
position -> previous -> next = position -> next;
position -> next -> previous = position -> previous;
return position;
}
ENetListIterator
enet_list_move (ENetListIterator position, void * dataFirst, void * dataLast)
{
ENetListIterator first = (ENetListIterator) dataFirst,
last = (ENetListIterator) dataLast;
first -> previous -> next = last -> next;
last -> next -> previous = first -> previous;
first -> previous = position -> previous;
last -> next = position;
first -> previous -> next = first;
position -> previous = last;
return first;
}
size_t
enet_list_size (ENetList * list)
{
size_t size = 0;
ENetListIterator position;
for (position = enet_list_begin (list);
position != enet_list_end (list);
position = enet_list_next (position))
++ size;
return size;
}
/** @} */

163
vendor/enet/packet.c vendored Normal file
View file

@ -0,0 +1,163 @@
/**
@file packet.c
@brief ENet packet management functions
*/
#include <string.h>
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
/** @defgroup Packet ENet packet functions
@{
*/
/** Creates a packet that may be sent to a peer.
@param data initial contents of the packet's data; the packet's data will remain uninitialized if data is NULL.
@param dataLength size of the data allocated for this packet
@param flags flags for this packet as described for the ENetPacket structure.
@returns the packet on success, NULL on failure
*/
ENetPacket *
enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags)
{
ENetPacket * packet = (ENetPacket *) enet_malloc (sizeof (ENetPacket));
if (packet == NULL)
return NULL;
if (flags & ENET_PACKET_FLAG_NO_ALLOCATE)
packet -> data = (enet_uint8 *) data;
else
if (dataLength <= 0)
packet -> data = NULL;
else
{
packet -> data = (enet_uint8 *) enet_malloc (dataLength);
if (packet -> data == NULL)
{
enet_free (packet);
return NULL;
}
if (data != NULL)
memcpy (packet -> data, data, dataLength);
}
packet -> referenceCount = 0;
packet -> flags = flags;
packet -> dataLength = dataLength;
packet -> freeCallback = NULL;
packet -> userData = NULL;
return packet;
}
/** Destroys the packet and deallocates its data.
@param packet packet to be destroyed
*/
void
enet_packet_destroy (ENetPacket * packet)
{
if (packet == NULL)
return;
if (packet -> freeCallback != NULL)
(* packet -> freeCallback) (packet);
if (! (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE) &&
packet -> data != NULL)
enet_free (packet -> data);
enet_free (packet);
}
/** Attempts to resize the data in the packet to length specified in the
dataLength parameter
@param packet packet to resize
@param dataLength new size for the packet data
@returns 0 on success, < 0 on failure
*/
int
enet_packet_resize (ENetPacket * packet, size_t dataLength)
{
enet_uint8 * newData;
if (dataLength <= packet -> dataLength || (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE))
{
packet -> dataLength = dataLength;
return 0;
}
newData = (enet_uint8 *) enet_malloc (dataLength);
if (newData == NULL)
return -1;
if (packet -> data != NULL)
{
if (packet -> dataLength > 0)
memcpy (newData, packet -> data, packet -> dataLength);
enet_free (packet -> data);
}
packet -> data = newData;
packet -> dataLength = dataLength;
return 0;
}
static const enet_uint32 crcTable [256] =
{
0, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x5005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0xBDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
enet_uint32
enet_crc32 (const ENetBuffer * buffers, size_t bufferCount)
{
enet_uint32 crc = 0xFFFFFFFF;
while (bufferCount -- > 0)
{
const enet_uint8 * data = (const enet_uint8 *) buffers -> data,
* dataEnd = & data [buffers -> dataLength];
while (data < dataEnd)
{
crc = (crc >> 8) ^ crcTable [(crc & 0xFF) ^ *data++];
}
++ buffers;
}
return ENET_HOST_TO_NET_32 (~ crc);
}
/** @} */

1030
vendor/enet/peer.c vendored Normal file

File diff suppressed because it is too large Load diff

1921
vendor/enet/protocol.c vendored Normal file

File diff suppressed because it is too large Load diff

630
vendor/enet/unix.c vendored Normal file
View file

@ -0,0 +1,630 @@
/**
@file unix.c
@brief ENet Unix system specific functions
*/
#ifndef _WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
#ifdef __APPLE__
#ifdef HAS_POLL
#undef HAS_POLL
#endif
#ifndef HAS_FCNTL
#define HAS_FCNTL 1
#endif
#ifndef HAS_INET_PTON
#define HAS_INET_PTON 1
#endif
#ifndef HAS_INET_NTOP
#define HAS_INET_NTOP 1
#endif
#ifndef HAS_MSGHDR_FLAGS
#define HAS_MSGHDR_FLAGS 1
#endif
#ifndef HAS_SOCKLEN_T
#define HAS_SOCKLEN_T 1
#endif
#ifndef HAS_GETADDRINFO
#define HAS_GETADDRINFO 1
#endif
#ifndef HAS_GETNAMEINFO
#define HAS_GETNAMEINFO 1
#endif
#endif
#ifdef HAS_FCNTL
#include <fcntl.h>
#endif
#ifdef HAS_POLL
#include <poll.h>
#endif
#if !defined(HAS_SOCKLEN_T) && !defined(__socklen_t_defined)
typedef int socklen_t;
#endif
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
static enet_uint32 timeBase = 0;
int
enet_initialize (void)
{
return 0;
}
void
enet_deinitialize (void)
{
}
enet_uint32
enet_host_random_seed (void)
{
return (enet_uint32) time (NULL);
}
enet_uint32
enet_time_get (void)
{
struct timeval timeVal;
gettimeofday (& timeVal, NULL);
return timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - timeBase;
}
void
enet_time_set (enet_uint32 newTimeBase)
{
struct timeval timeVal;
gettimeofday (& timeVal, NULL);
timeBase = timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - newTimeBase;
}
int
enet_address_set_host_ip (ENetAddress * address, const char * name)
{
#ifdef HAS_INET_PTON
if (! inet_pton (AF_INET, name, & address -> host))
#else
if (! inet_aton (name, (struct in_addr *) & address -> host))
#endif
return -1;
return 0;
}
int
enet_address_set_host (ENetAddress * address, const char * name)
{
#ifdef HAS_GETADDRINFO
struct addrinfo hints, * resultList = NULL, * result = NULL;
memset (& hints, 0, sizeof (hints));
hints.ai_family = AF_INET;
if (getaddrinfo (name, NULL, NULL, & resultList) != 0)
return -1;
for (result = resultList; result != NULL; result = result -> ai_next)
{
if (result -> ai_family == AF_INET && result -> ai_addr != NULL && result -> ai_addrlen >= sizeof (struct sockaddr_in))
{
struct sockaddr_in * sin = (struct sockaddr_in *) result -> ai_addr;
address -> host = sin -> sin_addr.s_addr;
freeaddrinfo (resultList);
return 0;
}
}
if (resultList != NULL)
freeaddrinfo (resultList);
#else
struct hostent * hostEntry = NULL;
#ifdef HAS_GETHOSTBYNAME_R
struct hostent hostData;
char buffer [2048];
int errnum;
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__GNU__)
gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
#else
hostEntry = gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & errnum);
#endif
#else
hostEntry = gethostbyname (name);
#endif
if (hostEntry != NULL && hostEntry -> h_addrtype == AF_INET)
{
address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0];
return 0;
}
#endif
return enet_address_set_host_ip (address, name);
}
int
enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
{
#ifdef HAS_INET_NTOP
if (inet_ntop (AF_INET, & address -> host, name, nameLength) == NULL)
#else
char * addr = inet_ntoa (* (struct in_addr *) & address -> host);
if (addr != NULL)
{
size_t addrLen = strlen(addr);
if (addrLen >= nameLength)
return -1;
memcpy (name, addr, addrLen + 1);
}
else
#endif
return -1;
return 0;
}
int
enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
{
#ifdef HAS_GETNAMEINFO
struct sockaddr_in sin;
int err;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
err = getnameinfo ((struct sockaddr *) & sin, sizeof (sin), name, nameLength, NULL, 0, NI_NAMEREQD);
if (! err)
{
if (name != NULL && nameLength > 0 && ! memchr (name, '\0', nameLength))
return -1;
return 0;
}
if (err != EAI_NONAME)
return -1;
#else
struct in_addr in;
struct hostent * hostEntry = NULL;
#ifdef HAS_GETHOSTBYADDR_R
struct hostent hostData;
char buffer [2048];
int errnum;
in.s_addr = address -> host;
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__GNU__)
gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
#else
hostEntry = gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & errnum);
#endif
#else
in.s_addr = address -> host;
hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET);
#endif
if (hostEntry != NULL)
{
size_t hostLen = strlen (hostEntry -> h_name);
if (hostLen >= nameLength)
return -1;
memcpy (name, hostEntry -> h_name, hostLen + 1);
return 0;
}
#endif
return enet_address_get_host_ip (address, name, nameLength);
}
int
enet_socket_bind (ENetSocket socket, const ENetAddress * address)
{
struct sockaddr_in sin;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
if (address != NULL)
{
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
}
else
{
sin.sin_port = 0;
sin.sin_addr.s_addr = INADDR_ANY;
}
return bind (socket,
(struct sockaddr *) & sin,
sizeof (struct sockaddr_in));
}
int
enet_socket_get_address (ENetSocket socket, ENetAddress * address)
{
struct sockaddr_in sin;
socklen_t sinLength = sizeof (struct sockaddr_in);
if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1)
return -1;
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
return 0;
}
int
enet_socket_listen (ENetSocket socket, int backlog)
{
return listen (socket, backlog < 0 ? SOMAXCONN : backlog);
}
ENetSocket
enet_socket_create (ENetSocketType type)
{
return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
}
int
enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
{
int result = -1;
switch (option)
{
case ENET_SOCKOPT_NONBLOCK:
#ifdef HAS_FCNTL
result = fcntl (socket, F_SETFL, (value ? O_NONBLOCK : 0) | (fcntl (socket, F_GETFL) & ~O_NONBLOCK));
#else
result = ioctl (socket, FIONBIO, & value);
#endif
break;
case ENET_SOCKOPT_BROADCAST:
result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_REUSEADDR:
result = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_RCVBUF:
result = setsockopt (socket, SOL_SOCKET, SO_RCVBUF, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_SNDBUF:
result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_RCVTIMEO:
{
struct timeval timeVal;
timeVal.tv_sec = value / 1000;
timeVal.tv_usec = (value % 1000) * 1000;
result = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) & timeVal, sizeof (struct timeval));
break;
}
case ENET_SOCKOPT_SNDTIMEO:
{
struct timeval timeVal;
timeVal.tv_sec = value / 1000;
timeVal.tv_usec = (value % 1000) * 1000;
result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & timeVal, sizeof (struct timeval));
break;
}
case ENET_SOCKOPT_NODELAY:
result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_TTL:
result = setsockopt (socket, IPPROTO_IP, IP_TTL, (char *) & value, sizeof (int));
break;
default:
break;
}
return result == -1 ? -1 : 0;
}
int
enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value)
{
int result = -1;
socklen_t len;
switch (option)
{
case ENET_SOCKOPT_ERROR:
len = sizeof (int);
result = getsockopt (socket, SOL_SOCKET, SO_ERROR, value, & len);
break;
case ENET_SOCKOPT_TTL:
len = sizeof (int);
result = getsockopt (socket, IPPROTO_IP, IP_TTL, (char *) value, & len);
break;
default:
break;
}
return result == -1 ? -1 : 0;
}
int
enet_socket_connect (ENetSocket socket, const ENetAddress * address)
{
struct sockaddr_in sin;
int result;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in));
if (result == -1 && errno == EINPROGRESS)
return 0;
return result;
}
ENetSocket
enet_socket_accept (ENetSocket socket, ENetAddress * address)
{
int result;
struct sockaddr_in sin;
socklen_t sinLength = sizeof (struct sockaddr_in);
result = accept (socket,
address != NULL ? (struct sockaddr *) & sin : NULL,
address != NULL ? & sinLength : NULL);
if (result == -1)
return ENET_SOCKET_NULL;
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
}
return result;
}
int
enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how)
{
return shutdown (socket, (int) how);
}
void
enet_socket_destroy (ENetSocket socket)
{
if (socket != -1)
close (socket);
}
int
enet_socket_send (ENetSocket socket,
const ENetAddress * address,
const ENetBuffer * buffers,
size_t bufferCount)
{
struct msghdr msgHdr;
struct sockaddr_in sin;
int sentLength;
memset (& msgHdr, 0, sizeof (struct msghdr));
if (address != NULL)
{
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
msgHdr.msg_name = & sin;
msgHdr.msg_namelen = sizeof (struct sockaddr_in);
}
msgHdr.msg_iov = (struct iovec *) buffers;
msgHdr.msg_iovlen = bufferCount;
sentLength = sendmsg (socket, & msgHdr, MSG_NOSIGNAL);
if (sentLength == -1)
{
if (errno == EWOULDBLOCK)
return 0;
return -1;
}
return sentLength;
}
int
enet_socket_receive (ENetSocket socket,
ENetAddress * address,
ENetBuffer * buffers,
size_t bufferCount)
{
struct msghdr msgHdr;
struct sockaddr_in sin;
int recvLength;
memset (& msgHdr, 0, sizeof (struct msghdr));
if (address != NULL)
{
msgHdr.msg_name = & sin;
msgHdr.msg_namelen = sizeof (struct sockaddr_in);
}
msgHdr.msg_iov = (struct iovec *) buffers;
msgHdr.msg_iovlen = bufferCount;
recvLength = recvmsg (socket, & msgHdr, MSG_NOSIGNAL);
if (recvLength == -1)
{
switch (errno)
{
case EWOULDBLOCK:
return 0;
case EINTR:
case EMSGSIZE:
return -2;
default:
return -1;
}
}
#ifdef HAS_MSGHDR_FLAGS
if (msgHdr.msg_flags & MSG_TRUNC)
return -2;
#endif
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
}
return recvLength;
}
int
enet_socketset_select (ENetSocket maxSocket, ENetSocketSet * readSet, ENetSocketSet * writeSet, enet_uint32 timeout)
{
struct timeval timeVal;
timeVal.tv_sec = timeout / 1000;
timeVal.tv_usec = (timeout % 1000) * 1000;
return select (maxSocket + 1, readSet, writeSet, NULL, & timeVal);
}
int
enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeout)
{
#ifdef HAS_POLL
struct pollfd pollSocket;
int pollCount;
pollSocket.fd = socket;
pollSocket.events = 0;
if (* condition & ENET_SOCKET_WAIT_SEND)
pollSocket.events |= POLLOUT;
if (* condition & ENET_SOCKET_WAIT_RECEIVE)
pollSocket.events |= POLLIN;
pollCount = poll (& pollSocket, 1, timeout);
if (pollCount < 0)
{
if (errno == EINTR && * condition & ENET_SOCKET_WAIT_INTERRUPT)
{
* condition = ENET_SOCKET_WAIT_INTERRUPT;
return 0;
}
return -1;
}
* condition = ENET_SOCKET_WAIT_NONE;
if (pollCount == 0)
return 0;
if (pollSocket.revents & POLLOUT)
* condition |= ENET_SOCKET_WAIT_SEND;
if (pollSocket.revents & POLLIN)
* condition |= ENET_SOCKET_WAIT_RECEIVE;
return 0;
#else
fd_set readSet, writeSet;
struct timeval timeVal;
int selectCount;
timeVal.tv_sec = timeout / 1000;
timeVal.tv_usec = (timeout % 1000) * 1000;
FD_ZERO (& readSet);
FD_ZERO (& writeSet);
if (* condition & ENET_SOCKET_WAIT_SEND)
FD_SET (socket, & writeSet);
if (* condition & ENET_SOCKET_WAIT_RECEIVE)
FD_SET (socket, & readSet);
selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal);
if (selectCount < 0)
{
if (errno == EINTR && * condition & ENET_SOCKET_WAIT_INTERRUPT)
{
* condition = ENET_SOCKET_WAIT_INTERRUPT;
return 0;
}
return -1;
}
* condition = ENET_SOCKET_WAIT_NONE;
if (selectCount == 0)
return 0;
if (FD_ISSET (socket, & writeSet))
* condition |= ENET_SOCKET_WAIT_SEND;
if (FD_ISSET (socket, & readSet))
* condition |= ENET_SOCKET_WAIT_RECEIVE;
return 0;
#endif
}
#endif

455
vendor/enet/win32.c vendored Normal file
View file

@ -0,0 +1,455 @@
/**
@file win32.c
@brief ENet Win32 system specific functions
*/
#ifdef _WIN32
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
#include <windows.h>
#include <mmsystem.h>
#include <ws2tcpip.h>
static enet_uint32 timeBase = 0;
int
enet_initialize (void)
{
WORD versionRequested = MAKEWORD (1, 1);
WSADATA wsaData;
if (WSAStartup (versionRequested, & wsaData))
return -1;
if (LOBYTE (wsaData.wVersion) != 1||
HIBYTE (wsaData.wVersion) != 1)
{
WSACleanup ();
return -1;
}
timeBeginPeriod (1);
return 0;
}
void
enet_deinitialize (void)
{
timeEndPeriod (1);
WSACleanup ();
}
enet_uint32
enet_host_random_seed (void)
{
return (enet_uint32) timeGetTime ();
}
enet_uint32
enet_time_get (void)
{
return (enet_uint32) timeGetTime () - timeBase;
}
void
enet_time_set (enet_uint32 newTimeBase)
{
timeBase = (enet_uint32) timeGetTime () - newTimeBase;
}
int
enet_address_set_host_ip (ENetAddress * address, const char * name)
{
enet_uint8 vals [4] = { 0, 0, 0, 0 };
int i;
for (i = 0; i < 4; ++ i)
{
const char * next = name + 1;
if (* name != '0')
{
long val = strtol (name, (char **) & next, 10);
if (val < 0 || val > 255 || next == name || next - name > 3)
return -1;
vals [i] = (enet_uint8) val;
}
if (* next != (i < 3 ? '.' : '\0'))
return -1;
name = next + 1;
}
memcpy (& address -> host, vals, sizeof (enet_uint32));
return 0;
}
int
enet_address_set_host (ENetAddress * address, const char * name)
{
struct hostent * hostEntry;
hostEntry = gethostbyname (name);
if (hostEntry == NULL ||
hostEntry -> h_addrtype != AF_INET)
return enet_address_set_host_ip (address, name);
address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0];
return 0;
}
int
enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
{
char * addr = inet_ntoa (* (struct in_addr *) & address -> host);
if (addr == NULL)
return -1;
else
{
size_t addrLen = strlen(addr);
if (addrLen >= nameLength)
return -1;
memcpy (name, addr, addrLen + 1);
}
return 0;
}
int
enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
{
struct in_addr in;
struct hostent * hostEntry;
in.s_addr = address -> host;
hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET);
if (hostEntry == NULL)
return enet_address_get_host_ip (address, name, nameLength);
else
{
size_t hostLen = strlen (hostEntry -> h_name);
if (hostLen >= nameLength)
return -1;
memcpy (name, hostEntry -> h_name, hostLen + 1);
}
return 0;
}
int
enet_socket_bind (ENetSocket socket, const ENetAddress * address)
{
struct sockaddr_in sin;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
if (address != NULL)
{
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
}
else
{
sin.sin_port = 0;
sin.sin_addr.s_addr = INADDR_ANY;
}
return bind (socket,
(struct sockaddr *) & sin,
sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0;
}
int
enet_socket_get_address (ENetSocket socket, ENetAddress * address)
{
struct sockaddr_in sin;
int sinLength = sizeof (struct sockaddr_in);
if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1)
return -1;
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
return 0;
}
int
enet_socket_listen (ENetSocket socket, int backlog)
{
return listen (socket, backlog < 0 ? SOMAXCONN : backlog) == SOCKET_ERROR ? -1 : 0;
}
ENetSocket
enet_socket_create (ENetSocketType type)
{
return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
}
int
enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
{
int result = SOCKET_ERROR;
switch (option)
{
case ENET_SOCKOPT_NONBLOCK:
{
u_long nonBlocking = (u_long) value;
result = ioctlsocket (socket, FIONBIO, & nonBlocking);
break;
}
case ENET_SOCKOPT_BROADCAST:
result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_REUSEADDR:
result = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_RCVBUF:
result = setsockopt (socket, SOL_SOCKET, SO_RCVBUF, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_SNDBUF:
result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_RCVTIMEO:
result = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_SNDTIMEO:
result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_NODELAY:
result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_TTL:
result = setsockopt (socket, IPPROTO_IP, IP_TTL, (char *) & value, sizeof (int));
break;
default:
break;
}
return result == SOCKET_ERROR ? -1 : 0;
}
int
enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value)
{
int result = SOCKET_ERROR, len;
switch (option)
{
case ENET_SOCKOPT_ERROR:
len = sizeof(int);
result = getsockopt (socket, SOL_SOCKET, SO_ERROR, (char *) value, & len);
break;
case ENET_SOCKOPT_TTL:
len = sizeof(int);
result = getsockopt (socket, IPPROTO_IP, IP_TTL, (char *) value, & len);
break;
default:
break;
}
return result == SOCKET_ERROR ? -1 : 0;
}
int
enet_socket_connect (ENetSocket socket, const ENetAddress * address)
{
struct sockaddr_in sin;
int result;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in));
if (result == SOCKET_ERROR && WSAGetLastError () != WSAEWOULDBLOCK)
return -1;
return 0;
}
ENetSocket
enet_socket_accept (ENetSocket socket, ENetAddress * address)
{
SOCKET result;
struct sockaddr_in sin;
int sinLength = sizeof (struct sockaddr_in);
result = accept (socket,
address != NULL ? (struct sockaddr *) & sin : NULL,
address != NULL ? & sinLength : NULL);
if (result == INVALID_SOCKET)
return ENET_SOCKET_NULL;
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
}
return result;
}
int
enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how)
{
return shutdown (socket, (int) how) == SOCKET_ERROR ? -1 : 0;
}
void
enet_socket_destroy (ENetSocket socket)
{
if (socket != INVALID_SOCKET)
closesocket (socket);
}
int
enet_socket_send (ENetSocket socket,
const ENetAddress * address,
const ENetBuffer * buffers,
size_t bufferCount)
{
struct sockaddr_in sin;
DWORD sentLength = 0;
if (address != NULL)
{
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
}
if (WSASendTo (socket,
(LPWSABUF) buffers,
(DWORD) bufferCount,
& sentLength,
0,
address != NULL ? (struct sockaddr *) & sin : NULL,
address != NULL ? sizeof (struct sockaddr_in) : 0,
NULL,
NULL) == SOCKET_ERROR)
{
if (WSAGetLastError () == WSAEWOULDBLOCK)
return 0;
return -1;
}
return (int) sentLength;
}
int
enet_socket_receive (ENetSocket socket,
ENetAddress * address,
ENetBuffer * buffers,
size_t bufferCount)
{
INT sinLength = sizeof (struct sockaddr_in);
DWORD flags = 0,
recvLength = 0;
struct sockaddr_in sin;
if (WSARecvFrom (socket,
(LPWSABUF) buffers,
(DWORD) bufferCount,
& recvLength,
& flags,
address != NULL ? (struct sockaddr *) & sin : NULL,
address != NULL ? & sinLength : NULL,
NULL,
NULL) == SOCKET_ERROR)
{
switch (WSAGetLastError ())
{
case WSAEWOULDBLOCK:
case WSAECONNRESET:
return 0;
case WSAEINTR:
case WSAEMSGSIZE:
return -2;
default:
return -1;
}
}
if (flags & MSG_PARTIAL)
return -2;
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
}
return (int) recvLength;
}
int
enet_socketset_select (ENetSocket maxSocket, ENetSocketSet * readSet, ENetSocketSet * writeSet, enet_uint32 timeout)
{
struct timeval timeVal;
timeVal.tv_sec = timeout / 1000;
timeVal.tv_usec = (timeout % 1000) * 1000;
return select (maxSocket + 1, readSet, writeSet, NULL, & timeVal);
}
int
enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeout)
{
fd_set readSet, writeSet;
struct timeval timeVal;
int selectCount;
timeVal.tv_sec = timeout / 1000;
timeVal.tv_usec = (timeout % 1000) * 1000;
FD_ZERO (& readSet);
FD_ZERO (& writeSet);
if (* condition & ENET_SOCKET_WAIT_SEND)
FD_SET (socket, & writeSet);
if (* condition & ENET_SOCKET_WAIT_RECEIVE)
FD_SET (socket, & readSet);
selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal);
if (selectCount < 0)
return -1;
* condition = ENET_SOCKET_WAIT_NONE;
if (selectCount == 0)
return 0;
if (FD_ISSET (socket, & writeSet))
* condition |= ENET_SOCKET_WAIT_SEND;
if (FD_ISSET (socket, & readSet))
* condition |= ENET_SOCKET_WAIT_RECEIVE;
return 0;
}
#endif

9
vendor/mariadb/.gitattributes vendored Normal file
View file

@ -0,0 +1,9 @@
# Normalise line endings:
* text=auto
# Prevent certain files from being exported:
.gitattributes export-ignore
.gitignore export-ignore
# merge
.travis.yml merge=cc

212
vendor/mariadb/.github/workflows/ci.yml vendored Normal file
View file

@ -0,0 +1,212 @@
---
name: Run CI Tests
on:
push:
branches: ['3.*']
pull_request:
workflow_dispatch:
schedule:
# Run weekly on Sundays at 2 AM UTC
- cron: '0 2 * * 0'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
jobs:
setup:
runs-on: ubuntu-latest
if: |
github.event_name != 'schedule' ||
startsWith(github.ref, 'refs/heads/3.4') ||
startsWith(github.ref, 'refs/heads/3.2') ||
startsWith(github.ref, 'refs/heads/3.1')
outputs:
matrix: ${{ steps.set-matrix.outputs.final-matrix }}
steps:
- uses: actions/checkout@v6
- id: set-matrix
name: build matrix
uses: mariadb-corporation/connector-ci-build-matrix@main
with:
additional-matrix: '[{"name": "MariaDB 11.4 (local) - windows 2025", "os": "windows-2025", "db-type": "community", "db-tag": "11.4"},{"name": "MariaDB 11.4 32bits (local) - windows 2025", "os": "windows-2025", "db-type": "community", "db-tag": "11.4", "arch": "32"}]'
ci-server:
name: server ${{ matrix.server.version }} test suite ${{ matrix.server.env && format(' {0}', matrix.server.env) || '' }}
runs-on: ubuntu-latest
continue-on-error: true
strategy:
fail-fast: false
matrix:
server:
- version: '11.4'
- version: '11.8'
env: TEST_OPTION=--ps-protocol
steps:
- name: Retrieve server ${{ matrix.server.version }}
shell: bash
run: |
# get latest server
git clone -b ${server_branch} https://github.com/mariadb/server ./workdir-server --depth=1
env:
server_branch: ${{ matrix.server.version }}
- name: Update libmariadb submodule for PR
if: github.event_name == 'pull_request'
shell: bash
run: |
cd ./workdir-server
git submodule update --init --remote libmariadb
cd libmariadb
git fetch origin ${{ github.event.pull_request.head.sha }}
git checkout -qf FETCH_HEAD
- name: Update libmariadb submodule for non-PR
if: github.event_name != 'pull_request'
shell: bash
run: |
cd ./workdir-server
git submodule set-branch -b ${{ github.ref_name }} libmariadb
git submodule sync
git submodule update --init --remote libmariadb
cd libmariadb
git checkout ${{ github.sha }}
- name: install ubuntu/macos requirement
run: |
sudo apt install libio-socket-ssl-perl
- name: Make server
shell: bash
run: |
cd ./workdir-server
git add libmariadb
mkdir bld
cd bld
cmake .. -DWITHOUT_DYNAMIC_PLUGINS=1
make -j9
- name: Run test suite
shell: bash
run: |
ls -lrt
cd ./workdir-server/bld/mysql-test/
ls -lrt
./mysql-test-run.pl --suite=main,unit ${TEST_OPTION} --parallel=auto --skip-test=session_tracker_last_gtid
env:
TEST_OPTION: ${{ matrix.server.env.TEST_OPTION }}
MYSQL_TEST_HOST: 127.0.0.1
- name: Archive error logs
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
retention-days: 5
name: log-files-${{ matrix.server.version }}
path: |
${{ github.workspace }}/workdir-server/bld/mysql-test/var/**/log/*.err
ci-clang:
name: clang build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: install clang
run: |
sudo apt-get update
sudo apt-get install -y clang
- name: build with clang
run: |
clang --version
cmake . -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWITH_EXTERNAL_ZLIB=On \
-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
make -j$(nproc)
ci:
name: ${{ matrix.name }}
needs: setup
timeout-minutes: 50
env:
MYSQL_TEST_HOST: mariadb.example.com
MYSQL_TEST_PORT: 3306
MYSQL_TEST_USER: testuser
MYSQL_TEST_PASSWD: "heyPassw-!*20oRd"
MYSQL_TEST_DB: testc
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.setup.outputs.matrix) }}
runs-on: ${{ matrix.os }}
continue-on-error: ${{ matrix.continue-on-error || matrix.os == 'macos-latest' }}
steps:
- uses: actions/checkout@v6
- name: Setup Test Environment
id: setup-env
uses: mariadb-corporation/connector-ci-setup@master
with:
db-type: ${{ matrix.db-type }}
db-tag: ${{ matrix.db-tag }}
test-db-password: ${{ env.MYSQL_TEST_PASSWD }}
test-db-database: ${{ env.MYSQL_TEST_DB }}
test-db-port: ${{ env.MYSQL_TEST_PORT }}
additional-conf: ${{ matrix.additional-conf || '' }}
registry-user: ${{ matrix.db-type == 'enterprise' && secrets.ENTERPRISE_USER || (secrets.DOCKER_TOKEN != '' && secrets.DOCKER_LOGIN || '') }}
registry-password: ${{ matrix.db-type == 'enterprise' && secrets.ENTERPRISE_TOKEN || secrets.DOCKER_TOKEN }}
os: ${{ matrix.os }}
maxscale-tag: ${{ matrix.maxscale-tag || ''}}
- name: make ubuntu/macos
if: ${{ !startsWith(matrix.os, 'windows') }}
run: |
cmake . -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWITH_EXTERNAL_ZLIB=On
make
- name: make windows 64bits
if: ${{ startsWith(matrix.os, 'windows') && (matrix.arch != '32' || !matrix.arch) }}
run: |
cmake . -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWITH_CURL=ON -DWITH_MSI=ON
cmake --build . --config RelWithDebInfo
- name: make windows 32bits
if: ${{ startsWith(matrix.os, 'windows') && startsWith(matrix.arch, '32') }}
run: |
cmake -A Win32 . -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWITH_CURL=ON -DWITH_MSI=ON
cmake --build . --config RelWithDebInfo
- name: Run test suite
shell: bash
run: |
cd unittest/libmariadb
ctest -V --output-on-failure
env:
MARIADB_CC_TEST: 1
MYSQL_TEST_TLS: 0
MYSQL_TEST_SSL_PORT: ${{ env.TEST_MAXSCALE_TLS_PORT }}
srv: ${{ matrix.db-type }}
MAXSCALE_TAG: ${{ matrix.maxscale-tag || '' }}
MARIADB_PLUGIN_DIR: ${{ github.workspace }}
- name: MaxScale logs on failure
if: ${{ failure() && matrix.maxscale-tag != '' && !startsWith(matrix.os, 'windows') }}
shell: bash
run: |
echo "============================="
echo "=== MaxScale container(s) ==="
echo "============================="
podman ps -a --filter "name=maxscale" --format '{{.Names}} {{.Image}} {{.Status}}' || true
for c in $(podman ps -a --filter "name=maxscale" --format '{{.Names}}'); do
echo ""
echo "=== podman logs: $c ==="
podman logs "$c" 2>&1 | tail -n 500 || true
echo ""
echo "=== /var/log/maxscale/maxscale.log in $c ==="
podman exec "$c" sh -c 'tail -n 500 /var/log/maxscale/maxscale.log 2>/dev/null || cat /var/log/maxscale/maxscale.log 2>/dev/null' || true
done

118
vendor/mariadb/.gitignore vendored Normal file
View file

@ -0,0 +1,118 @@
CMakeCache.txt
CMakeFiles/*
Makefile
include/my_config.h
include/mysql_version.h
CMakeFiles
mysql_config/mysql_config.c
examples/mysql_affected_rows
examples/mysql_debug
examples/test_output
mysql_config/mysql_config
mariadb_config/libmariadb.pc
# Keep empty directories:
# Keep empty directories: >> .gitignore/.git*
# Compiled Static libraries
*.lib
*.a
*.la
*.lai
*.lo
# Compiled Dynamic libraries
*.so
*.so.*
*.dylib
*.dll
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
*.dgcov
.*.swp
.gdb_history
CTestTestfile.cmake
cmake_install.cmake
bin/
include/config.h
include/ma_config.h
include/mariadb/mariadb/
include/mariadb/ma_errmsg.h
include/mariadb/ma_list.h
include/mariadb/ma_pvio.h
include/mariadb/ma_tls.h
include/mariadb/mariadb_com.h
include/mariadb/mariadb_ctype.h
include/mariadb/mariadb_dyncol.h
include/mariadb/mariadb_stmt.h
include/mariadb/mariadb_version.h
include/mariadb/mysql.h
include/mariadb/mysql/
include/mariadb_version.h
lib/
libmariadb/home/
libmariadb/ma_client_plugin.c
libmariadb/mariadbclient.def
mariadb_config/mariadb_config
mariadb_config/mariadb_config.c
manpages.list
unittest/libmariadb/async
unittest/libmariadb/basic-t
unittest/libmariadb/bulk1
unittest/libmariadb/charset
unittest/libmariadb/connection
unittest/libmariadb/cursor
unittest/libmariadb/dyncol
unittest/libmariadb/errors
unittest/libmariadb/features-10_2
unittest/libmariadb/fetch
unittest/libmariadb/fingerprint.list
unittest/libmariadb/logs
unittest/libmariadb/misc
unittest/libmariadb/performance
unittest/libmariadb/ps
unittest/libmariadb/ps_bugs
unittest/libmariadb/ps_new
unittest/libmariadb/result
unittest/libmariadb/rpl_api
unittest/libmariadb/sp
unittest/libmariadb/sqlite3
unittest/libmariadb/ssl
unittest/libmariadb/t_aurora
unittest/libmariadb/t_conc173
unittest/libmariadb/thread
unittest/libmariadb/tls
unittest/libmariadb/tls.c
unittest/libmariadb/view
unittest/libmariadb/conc336
benchmark/benchmark/
benchmark/bld/
benchmark/mariadb.json
benchmark/mysql.json
benchmark/main-benchmark
#VS files/directories
*.vcxproj
*.filters
*.user
ipch
*.sln
*.suo
*.sdf
Win32
x64
*.dir
Debug
Release
RelWithDebInfo
#vim backups
*.*~

3
vendor/mariadb/.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "docs"]
path = docs
url = https://github.com/mariadb-corporation/mariadb-connector-c.wiki.git

34
vendor/mariadb/.travis.yml vendored Normal file
View file

@ -0,0 +1,34 @@
language: c
version: ~> 1.0
cache:
apt: true
ccache: true
directories:
- $HOME/docker
before_install:
- |-
if [ -z "$server_branch" ] ; then
case $TRAVIS_OS_NAME in
windows)
choco install python --version=3.12.0
python --version
;;
esac
fi
env:
global: local=0 DB=testc CLEAR_TEXT=0
import: mariadb-corporation/connector-test-machine:common-build.yml@master
jobs:
include:
- stage: Community
env: srv=mariadb v=10.11 local=1 TEST_OPTION=--ps-protocol
name: "CS 10.11 with ps-protocol"
- env: server_branch=11.4
name: "11.4 Server unit testing"
script: ./travis.sh

646
vendor/mariadb/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,646 @@
# CMakeLists.txt
# This is the LGPL libmariadb project.
CMAKE_MINIMUM_REQUIRED(VERSION 3.12.0 FATAL_ERROR)
INCLUDE(CheckFunctionExists)
# CMP0077 defaults to NEW since cmake 3.13; can drop when minimum is bumped
CMAKE_POLICY(SET CMP0077 NEW)
# Is C/C built as subproject?
get_directory_property(IS_SUBPROJECT PARENT_DIRECTORY)
# do not inherit include directories from the parent project
SET_PROPERTY(DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
FOREACH(V WITH_MYSQLCOMPAT WITH_MSI WITH_SIGNCODE WITH_RTC WITH_UNIT_TESTS
WITH_DYNCOL WITH_EXTERNAL_ZLIB WITH_CURL WITH_SQLITE WITH_SSL WITH_ICONV
DEFAULT_CHARSET INSTALL_LAYOUT WITH_TEST_SRCPKG WITH_BOOST_CONTEXT
DEFAULT_SSL_VERIFY_SERVER_CERT)
SET(${V} ${${OPT}${V}})
ENDFOREACH()
MACRO(ADD_OPTION _name _text _default)
IF(NOT DEFINED ${_name})
OPTION(${OPT}${_name} "${_text}" "${_default}")
ELSE()
OPTION(${OPT}${_name} "${_text}" "${${_name}}")
ENDIF()
ENDMACRO()
ADD_OPTION(WITH_BOOST_CONTEXT
"Use Boost::Context for the non-blocking API on platforms without native implementation"
OFF)
ADD_OPTION(WITH_TOOLS
"Build tools"
OFF)
IF(WITH_BOOST_CONTEXT)
PROJECT(mariadb-connector-c LANGUAGES C CXX)
ELSE()
PROJECT(mariadb-connector-c C)
ENDIF()
SET(CC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
SET(CC_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
SET(CPACK_PACKAGE_VERSION_MAJOR 3)
SET(CPACK_PACKAGE_VERSION_MINOR 4)
SET(CPACK_PACKAGE_VERSION_PATCH 10)
SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
MATH(EXPR MARIADB_PACKAGE_VERSION_ID "${CPACK_PACKAGE_VERSION_MAJOR} * 10000 +
${CPACK_PACKAGE_VERSION_MINOR} * 100 +
${CPACK_PACKAGE_VERSION_PATCH}")
### Options ###
IF(NOT WIN32)
ADD_OPTION(WITH_MYSQLCOMPAT "creates libmysql* symbolic links" OFF)
ADD_OPTION(WITH_DOCS "creates manpages" OFF)
ELSE()
ADD_OPTION(WITH_MSI "Build MSI installation package" OFF)
ADD_OPTION(WITH_SIGNCODE "digitally sign files" OFF)
ADD_OPTION(WITH_RTC "enables run time checks for debug builds" OFF)
ADD_OPTION(WITH_ICONV "enables character set conversion" OFF)
ENDIF()
ADD_OPTION(WITH_UNIT_TESTS "build test suite" ON)
ADD_OPTION(WITH_DYNCOL "Enables support of dynamic columns" ON)
ADD_OPTION(WITH_EXTERNAL_ZLIB "Enables use of external zlib" OFF)
ADD_OPTION(WITH_CURL "Enables use of curl" ON)
ADD_OPTION(WITH_SSL "Enables use of TLS/SSL library" ON)
ADD_OPTION(DEFAULT_SSL_VERIFY_SERVER_CERT "Default value for MYSQL_OPT_SSL_VERIFY_SERVER_CERT" ON)
IF(NOT IS_SUBPROJECT)
ADD_OPTION(WITH_ASAN
"Enable AddressSanitizer instrumentation for Debug and RelWithDebInfo builds"
OFF)
ADD_OPTION(WITH_ASAN_SCOPE
"Enable -fsanitize-address-use-after-scope for Clang ASAN builds"
OFF)
ADD_OPTION(WITH_UBSAN
"Enable UndefinedBehaviorSanitizer instrumentation for Debug and RelWithDebInfo builds"
OFF)
ADD_OPTION(WITH_MSAN "Enable MemorySanitizer instrumentation for Debug and RelWithDebInfo builds" OFF)
ENDIF()
INCLUDE(${CC_SOURCE_DIR}/cmake/misc.cmake)
FIND_PACKAGE(CURL)
IF(NOT IS_SUBPROJECT)
MACRO(MARIADB_ADD_SANITIZER_FLAGS compile_flags link_flags)
FOREACH(BUILD_TYPE DEBUG RELWITHDEBINFO)
SET(CMAKE_C_FLAGS_${BUILD_TYPE}
"${CMAKE_C_FLAGS_${BUILD_TYPE}} ${compile_flags}")
FOREACH(LINKER EXE SHARED MODULE)
SET(CMAKE_${LINKER}_LINKER_FLAGS_${BUILD_TYPE}
"${CMAKE_${LINKER}_LINKER_FLAGS_${BUILD_TYPE}} ${link_flags}")
ENDFOREACH()
ENDFOREACH()
ENDMACRO()
IF(WITH_MSAN AND (WITH_ASAN OR WITH_UBSAN))
MESSAGE(FATAL_ERROR "WITH_MSAN is incompatible with WITH_ASAN or WITH_UBSAN")
ENDIF()
IF(WITH_ASAN_SCOPE)
IF(NOT WITH_ASAN)
MESSAGE(FATAL_ERROR "WITH_ASAN_SCOPE requires WITH_ASAN")
ENDIF()
IF(NOT CMAKE_C_COMPILER_ID MATCHES "Clang")
MESSAGE(FATAL_ERROR "WITH_ASAN_SCOPE is supported only with Clang")
ENDIF()
ADD_COMPILE_OPTIONS(
"$<$<CONFIG:Debug>:-fsanitize-address-use-after-scope>"
"$<$<CONFIG:RelWithDebInfo>:-fsanitize-address-use-after-scope>")
ENDIF()
IF(WITH_ASAN)
IF(MSVC)
MARIADB_ADD_SANITIZER_FLAGS(
"/fsanitize=address /fsanitize-address-use-after-return"
"/INCREMENTAL:NO")
ELSE()
MARIADB_ADD_SANITIZER_FLAGS(
"-U_FORTIFY_SOURCE -fsanitize=address"
"-fsanitize=address")
ENDIF()
ENDIF()
IF(NOT MSVC)
IF(WITH_UBSAN)
MARIADB_ADD_SANITIZER_FLAGS(
"-fsanitize=undefined -U_FORTIFY_SOURCE"
"-fsanitize=undefined")
ENDIF()
IF(WITH_MSAN)
MARIADB_ADD_SANITIZER_FLAGS(
"-fsanitize=memory -fsanitize-memory-track-origins -U_FORTIFY_SOURCE"
"-fsanitize=memory -fsanitize-memory-track-origins")
ENDIF()
ENDIF()
ENDIF()
IF(WITH_SIGNCODE)
IF(WIN32 AND NOT SIGN_OPTIONS)
SET(SIGN_OPTIONS /tr http://timestamp.digicert.com /td sha256 /fd sha256 /a)
ELSE()
SEPARATE_ARGUMENTS(SIGN_OPTIONS)
ENDIF()
MARK_AS_ADVANCED(SIGN_OPTIONS)
ENDIF()
SET(MARIADB_CONNECTOR_C_COPYRIGHT "2013-2017 MariaDB Corporation Ab")
IF(WITH_RTC)
SET(RTC_OPTIONS "/RTC1 /RTCc")
ENDIF()
INCLUDE(${CC_SOURCE_DIR}/cmake/plugins.cmake)
IF(WIN32)
FILE(REMOVE ${CC_BINARY_DIR}/win/packaging/plugin.conf)
INCLUDE(${CC_SOURCE_DIR}/cmake/version_info.cmake)
ENDIF()
IF(NOT IS_SUBPROJECT)
IF(MSVC)
# Speedup system tests
INCLUDE(${CC_SOURCE_DIR}/cmake/WindowsCache.cmake)
add_compile_definitions(WIN32_LEAN_AND_MEAN NOGDI)
IF (MSVC)
SET(CONFIG_TYPES "DEBUG" "RELEASE" "RELWITHDEBINFO")
FOREACH(BUILD_TYPE ${CONFIG_TYPES})
FOREACH(COMPILER CXX C)
SET(COMPILER_FLAGS "${CMAKE_${COMPILER}_FLAGS_${BUILD_TYPE}}")
IF (NOT COMPILER_FLAGS STREQUAL "")
IF(NOT WITH_ASAN)
STRING(REPLACE "/MD" "/MT" COMPILER_FLAGS ${COMPILER_FLAGS})
IF (BUILD_TYPE STREQUAL "DEBUG")
SET(COMPILER_FLAGS "${COMPILER_FLAGS} ${RTC_OPTIONS}")
ENDIF()
ENDIF()
STRING(REPLACE "/Zi" "/Z7" COMPILER_FLAGS ${COMPILER_FLAGS})
MESSAGE (STATUS "CMAKE_${COMPILER}_FLAGS_${BUILD_TYPE}= ${COMPILER_FLAGS}")
SET(CMAKE_${COMPILER}_FLAGS_${BUILD_TYPE} ${COMPILER_FLAGS})
ENDIF()
ENDFOREACH()
ENDFOREACH()
ENDIF()
ENDIF()
ELSE()
# MDEV-16383
IF(WITH_EMBEDDED_SERVER)
add_compile_definitions(HAVE_EMBEDDED)
ENDIF()
ENDIF()
# Disable dbug information for release builds
SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DDBUG_OFF")
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DDBUG_OFF")
SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -DDBUG_OFF")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DDBUG_OFF")
IF(CMAKE_C_COMPILER_ID MATCHES "GNU")
INCLUDE(CheckCCompilerFlag)
SET(GCC_FLAGS -Wunused -Wlogical-op -Wno-uninitialized -Wall -Wextra -Wformat-security -Wno-init-self -Wwrite-strings -Wshift-count-overflow -Wdeclaration-after-statement -Wno-undef -Wno-unknown-pragmas -Wno-stringop-truncation)
FOREACH(GCC_FLAG ${GCC_FLAGS})
CHECK_C_COMPILER_FLAG("${GCC_FLAG}" HAS_${GCC_FLAG}_FLAG)
IF(${HAS_${GCC_FLAG}_FLAG})
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GCC_FLAG}")
ENDIF()
ENDFOREACH()
ENDIF()
# If the build type isn't specified, set to Relwithdebinfo as default.
IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE "RelWithDebInfo")
ENDIF()
FIND_PACKAGE(Git)
IF(GIT_EXECUTABLE AND EXISTS ${CC_SOURCE_DIR}/.git)
EXECUTE_PROCESS(
COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
WORKING_DIRECTORY ${CC_SOURCE_DIR}
OUTPUT_VARIABLE OUT RESULT_VARIABLE RES)
IF(RES EQUAL 0)
STRING(REGEX REPLACE "\n$" "" CC_SOURCE_REVISION "${OUT}")
ENDIF()
EXECUTE_PROCESS(
COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive
WORKING_DIRECTORY ${CC_SOURCE_DIR})
ENDIF()
# various defines for generating include/mysql_version.h
SET(PROTOCOL_VERSION 10) # we adapted new password option from PHP's mysqlnd !
# if C/C is build as subproject inside MariaDB server tree we will
# use the version defined by server
IF(MAJOR_VERSION)
SET(MARIADB_CLIENT_VERSION_MAJOR ${MAJOR_VERSION})
SET(MARIADB_CLIENT_VERSION_MINOR ${MINOR_VERSION})
SET(MARIADB_CLIENT_VERSION_PATCH ${PATCH_VERSION})
SET(MARIADB_CLIENT_VERSION_EXTRA ${EXTRA_VERSION})
ELSE()
SET(MARIADB_CLIENT_VERSION_MAJOR "10")
SET(MARIADB_CLIENT_VERSION_MINOR "8")
SET(MARIADB_CLIENT_VERSION_PATCH "8")
SET(MARIADB_CLIENT_VERSION_EXTRA "")
ENDIF()
IF(WIN32)
# version in resource files need to be consistent
# with server's , so that MSI minor upgrade work.
# if this is not a subproject build, C/C version is used.
FOREACH(v MAJOR MINOR PATCH TINY)
IF(DEFINED ${v}_VERSION)
SET(${v}_FILE_VERSION "${${v}_VERSION}")
ELSEIF(DEFINED CPACK_PACKAGE_VERSION_${v})
SET(${v}_FILE_VERSION "${CPACK_PACKAGE_VERSION_${v}}")
ELSE()
SET(${v}_FILE_VERSION "0")
ENDIF()
IF(NOT ${v}_FILE_VERSION MATCHES "^[0-9]+$")
MESSAGE(FATAL_ERROR
"${v}_FILE_VERSION is not numeric - '${${v}_FILE_VERSION}'")
ENDIF()
ENDFOREACH()
ENDIF()
SET(MARIADB_CLIENT_VERSION "${MARIADB_CLIENT_VERSION_MAJOR}.${MARIADB_CLIENT_VERSION_MINOR}.${MARIADB_CLIENT_VERSION_PATCH}${MARIADB_CLIENT_VERSION_EXTRA}")
SET(MARIADB_BASE_VERSION "mariadb-${MARIADB_CLIENT_VERSION_MAJOR}.${MARIADB_CLIENT_VERSION_MINOR}")
MATH(EXPR MARIADB_VERSION_ID "${MARIADB_CLIENT_VERSION_MAJOR} * 10000 +
${MARIADB_CLIENT_VERSION_MINOR} * 100 +
${MARIADB_CLIENT_VERSION_PATCH}")
IF (NOT MARIADB_PORT)
SET(MARIADB_PORT 3306)
ENDIF ()
IF(NOT MARIADB_UNIX_ADDR)
SET(MARIADB_UNIX_ADDR "/tmp/mysql.sock")
ENDIF()
INCLUDE("${CC_SOURCE_DIR}/cmake/install.cmake")
IF(NOT PLUGINDIR)
SET(PLUGINDIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_PLUGINDIR}")
ENDIF()
# todo: we don't character sets in share - all is compiled in
SET(SHAREDIR "share")
SET(DEFAULT_CHARSET_HOME "${CMAKE_INSTALL_PREFIX}")
INCLUDE(${CC_SOURCE_DIR}/cmake/SearchLibrary.cmake)
# Compression plugins: ZSTD, ZLIB
INCLUDE(${CC_SOURCE_DIR}/cmake/FindZStd.cmake)
IF(WITH_EXTERNAL_ZLIB)
IF(NOT ZLIB_FOUND)
FIND_PACKAGE(ZLIB REQUIRED)
ENDIF()
SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${ZLIB_LIBRARIES})
ELSE()
SET(ZLIB_INCLUDE_DIR "${CC_SOURCE_DIR}/external/zlib")
ADD_SUBDIRECTORY("${CC_SOURCE_DIR}/external/zlib")
ENDIF()
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
IF(NOT WIN32)
INCLUDE(TestBigEndian)
TEST_BIG_ENDIAN(HAVE_BIGENDIAN)
ENDIF()
# check for various include files
INCLUDE(${CC_SOURCE_DIR}/cmake/check_include_files.cmake)
# check for various functions
INCLUDE(${CC_SOURCE_DIR}/cmake/check_functions.cmake)
# check for various types
INCLUDE(${CC_SOURCE_DIR}/cmake/check_types.cmake)
IF(UNIX)
SEARCH_LIBRARY(LIBM floor m)
SEARCH_LIBRARY(LIBPTHREAD pthread_getspecific "pthread;pthreads")
SEARCH_LIBRARY(LIBNSL gethostbyname_r "nsl_r;nsl")
SEARCH_LIBRARY(LIBSOCKET setsockopt socket)
FIND_PACKAGE(Threads)
SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${LIBNSL} ${LIBBIND} ${LIBICONV} ${ZLIB_LIBRARY}
${LIBSOCKET} ${CMAKE_DL_LIBS} ${LIBM} ${LIBPTHREAD})
SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${LIBNSL} ${LIBBIND} ${LIBICONV}
${LIBSOCKET} ${CMAKE_DL_LIBS} ${LIBM} ${LIBPTHREAD})
#remove possible dups from required libraries
LIST(LENGTH CMAKE_REQUIRED_LIBRARIES rllength)
IF(${rllength} GREATER 0)
LIST(REMOVE_DUPLICATES CMAKE_REQUIRED_LIBRARIES)
ENDIF()
ENDIF()
IF(CMAKE_HAVE_PTHREAD_H)
SET(CMAKE_REQUIRED_INCLUDES pthread.h)
ENDIF()
IF(DBUG_OFF)
add_compile_definitions(DBUG_OFF=1)
ENDIF()
add_compile_definitions(MARIADB_SYSTEM_TYPE="${CMAKE_SYSTEM_NAME}")
add_compile_definitions(MARIADB_MACHINE_TYPE="${CMAKE_SYSTEM_PROCESSOR}")
IF(WIN32)
add_compile_definitions(HAVE_DLOPEN)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_DEPRECATE)
ENDIF()
IF(NOT DEFAULT_CHARSET)
SET(DEFAULT_CHARSET "utf8mb4")
ENDIF()
# convert SSL options to uppercase
IF(WITH_SSL)
STRING(TOUPPER ${WITH_SSL} WITH_SSL)
ENDIF()
IF(WITH_SSL STREQUAL "ON")
IF(WIN32)
SET(WITH_SSL "SCHANNEL")
ELSE()
SET(WITH_SSL "OPENSSL")
ENDIF()
ENDIF()
IF(WITH_SSL STREQUAL "OPENSSL")
IF (NOT OPENSSL_FOUND)
FIND_PACKAGE(OpenSSL)
ENDIF()
IF(OPENSSL_FOUND)
add_compile_definitions(HAVE_OPENSSL HAVE_TLS)
SET(SSL_SOURCES "${CC_SOURCE_DIR}/libmariadb/secure/openssl.c"
"${CC_SOURCE_DIR}/libmariadb/secure/openssl_crypt.c")
SET(SSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY})
IF(WIN32 AND EXISTS ${OPENSSL_INCLUDE_DIR}/openssl/applink.c)
SET(HAVE_OPENSSL_APPLINK_C 1)
ENDIF()
IF(EXISTS ${OPENSSL_INCLUDE_DIR}/openssl/evp.h)
SET(HAVE_evp_pkey 1)
ENDIF()
INCLUDE_DIRECTORIES(BEFORE ${OPENSSL_INCLUDE_DIR})
TRY_RUN(LIBRESSL_RESULT HAVE_LIBRESSL
${CMAKE_BINARY_DIR}
${CC_SOURCE_DIR}/cmake/libressl_version.c
COMPILE_DEFINITIONS "-I${OPENSSL_INCLUDE_DIR}"
RUN_OUTPUT_VARIABLE LIBRESSL_VERSION)
IF(HAVE_LIBRESSL)
add_compile_definitions(HAVE_LIBRESSL)
SET(TLS_LIBRARY_VERSION ${LIBRESSL_VERSION})
ELSE()
SET(TLS_LIBRARY_VERSION "OpenSSL ${OPENSSL_VERSION}")
ENDIF()
ELSE()
MESSAGE1(TLS_LIBRARY_VERSION "OpenSSL/LibreSSL not found")
ENDIF()
ELSEIF(WITH_SSL STREQUAL "GNUTLS")
FIND_PACKAGE(GnuTLS "3.4.2" REQUIRED)
IF(GNUTLS_FOUND)
add_compile_definitions(HAVE_GNUTLS HAVE_TLS)
SET(SSL_SOURCES "${CC_SOURCE_DIR}/libmariadb/secure/gnutls.c"
"${CC_SOURCE_DIR}/libmariadb/secure/gnutls_crypt.c")
GET_FILENAME_COMPONENT(LIB_EXT "${GNUTLS_LIBRARIES}" EXT)
LIST(APPEND SSL_LIBRARIES ${GNUTLS_LIBRARIES})
IF(LIB_EXT STREQUAL ".a")
# static library depends on zlib, and libdl
LIST(APPEND SSL_LIBRARIES ${ZLIB_LIBRARIES} ${CMAKE_DL_LIBS})
ENDIF()
SET(TLS_LIBRARY_VERSION "GnuTLS ${GNUTLS_VERSION_STRING}")
INCLUDE_DIRECTORIES(${GNUTLS_INCLUDE_DIR})
ELSE()
MESSAGE(FATAL_ERROR "GnuTLS not found")
ENDIF()
ELSEIF(WIN32 AND WITH_SSL STREQUAL "SCHANNEL")
add_compile_definitions(HAVE_SCHANNEL HAVE_TLS HAVE_WINCRYPT)
SET(SSL_SOURCES "${CC_SOURCE_DIR}/libmariadb/secure/schannel.c"
"${CC_SOURCE_DIR}/libmariadb/secure/win_crypt.c"
"${CC_SOURCE_DIR}/libmariadb/secure/ma_schannel.c"
"${CC_SOURCE_DIR}/libmariadb/secure/schannel_certs.c")
INCLUDE_DIRECTORIES("${CC_SOURCE_DIR}/plugins/pvio/")
SET(SSL_LIBRARIES secur32 crypt32 bcrypt)
SET(TLS_LIBRARY_VERSION "Schannel ${CMAKE_SYSTEM_VERSION}")
ELSE()
MESSAGE(FATAL_ERROR "Invalid TLS/SSL option '${WITH_SSL}'")
ENDIF()
MESSAGE1(TLS_LIBRARY_VERSION "TLS library/version: ${TLS_LIBRARY_VERSION}")
MARK_AS_ADVANCED(SSL_SOURCES)
IF(WITH_BOOST_CONTEXT)
FIND_PACKAGE(Boost 1.40 COMPONENTS context REQUIRED)
SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${Boost_LIBRARIES})
ENDIF()
SET(ENABLED_LOCAL_INFILE "AUTO" CACHE STRING "If we should should enable LOAD DATA LOCAL by default (OFF/ON/AUTO)")
MARK_AS_ADVANCED(ENABLED_LOCAL_INFILE)
IF (ENABLED_LOCAL_INFILE MATCHES "^(0|FALSE)$")
SET(ENABLED_LOCAL_INFILE OFF)
ELSEIF(ENABLED_LOCAL_INFILE MATCHES "^(1|TRUE)$")
SET(ENABLED_LOCAL_INFILE ON)
ELSEIF (NOT ENABLED_LOCAL_INFILE MATCHES "^(ON|OFF|AUTO)$")
MESSAGE(FATAL_ERROR "ENABLED_LOCAL_INFILE must be one of OFF, ON, AUTO")
ENDIF()
IF(WITH_ICONV)
IF(NOT WIN32)
INCLUDE(${CC_SOURCE_DIR}/cmake/FindIconv.cmake)
ENDIF()
ENDIF()
CONFIGURE_FILE(${CC_SOURCE_DIR}/include/ma_config.h.in
${CC_BINARY_DIR}/include/ma_config.h)
CONFIGURE_FILE(${CC_SOURCE_DIR}/include/ma_config.h.in
${CC_BINARY_DIR}/include/config.h)
CONFIGURE_FILE(${CC_SOURCE_DIR}/include/mariadb_version.h.in
${CC_BINARY_DIR}/include/mariadb_version.h)
INCLUDE_DIRECTORIES(${CC_BINARY_DIR}/include)
IF(WIN32)
SET(SYSTEM_LIBS ws2_32 advapi32 kernel32 shlwapi crypt32 bcrypt ${LIBZ})
ELSE()
SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${LIBPTHREAD} ${CMAKE_DL_LIBS} ${LIBM})
IF(ICONV_EXTERNAL)
SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${ICONV_LIBRARIES})
ENDIF()
ENDIF()
IF(WITH_SSL)
SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${SSL_LIBRARIES})
ENDIF()
MESSAGE1(SYSTEM_LIBS "SYSTEM_LIBS ${SYSTEM_LIBS}")
MARK_AS_ADVANCED(SYSTEM_LIBS)
IF(NOT IS_SUBPROJECT AND (NOT DEFINED CMAKE_COMPILE_WARNING_AS_ERROR))
IF ((NOT WIN32) AND (CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID MATCHES "GNU"))
SET(WARNING_AS_ERROR "-Werror")
ELSEIF(CMAKE_C_COMPILER_ID MATCHES "MSVC")
SET(WARNING_AS_ERROR "/WX")
ENDIF()
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_AS_ERROR}")
ENDIF()
IF(NOT REMOTEIO_PLUGIN_TYPE MATCHES "OFF")
IF(CURL_FOUND)
INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIRS})
IF(REMOTEIO_PLUGIN_TYPE MATCHES "STATIC")
SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${CURL_LIBRARIES})
ENDIF()
add_compile_definitions(HAVE_REMOTEIO=1)
ENDIF()
ENDIF()
IF(NOT WIN32)
IF(NOT AUTH_GSSAPI_PLUGIN_TYPE MATCHES "OFF")
INCLUDE(${CC_SOURCE_DIR}/cmake/FindGSSAPI.cmake)
IF(GSSAPI_FOUND)
INCLUDE_DIRECTORIES(${GSSAPI_INCS})
IF(AUTH_GSSAPI_PLUGIN_TYPE MATCHES "STATIC")
SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${GSSAPI_LIBS})
ENDIF()
ENDIF()
ENDIF()
ENDIF()
INCLUDE(${CC_SOURCE_DIR}/plugins/CMakeLists.txt)
ADD_SUBDIRECTORY(include)
ADD_SUBDIRECTORY(libmariadb)
IF((NOT WIN32) OR CYGWIN)
ADD_SUBDIRECTORY(mariadb_config)
ENDIF()
IF(WITH_TOOLS)
ADD_SUBDIRECTORY(tools)
ENDIF()
IF(IS_DIRECTORY ${CC_SOURCE_DIR}/unittest)
IF(WITH_UNIT_TESTS)
ADD_SUBDIRECTORY(unittest/mytap)
ADD_SUBDIRECTORY(unittest/libmariadb)
ENDIF()
ENDIF()
#IF(CLIENT_DOCS)
# INSTALL(DIRECTORY ${CLIENT_DOCS}
# DESTINATION ${DOCS_INSTALL_DIR_${INSTALL_LAYOUT}}
# COMPONENT SharedLibraries)
#ENDIF()
IF(UNIX)
ADD_SUBDIRECTORY(man)
ENDIF()
IF(WIN32 AND WITH_MSI AND CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
ADD_SUBDIRECTORY(win/packaging)
ENDIF()
MESSAGE1(SYSTEM_PROCESSOR "SYSTEM processor: ${CMAKE_SYSTEM_PROCESSOR}")
SET(CPACK_PACKAGE_VENDOR "MariaDB Corporation Ab")
SET(CPACK_PACKAGE_DESCRIPTION "MariaDB Connector/C. A library for connecting to MariaDB and MySQL servers")
SET(CPACK_PACKAGE_NAME "mariadb_connector_c")
STRING(TOLOWER ${CMAKE_SYSTEM_NAME} system_name)
SET(CPACK_RESOURCE_FILE_LICENSE "${CC_SOURCE_DIR}/COPYING.LIB")
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CC_SOURCE_DIR}/README")
INCLUDE(cmake/ConnectorName.cmake)
IF(NOT PACKAGE_STATUS_SUFFIX)
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-src")
IF(PACKAGE_PLATFORM_SUFFIX)
SET(CPACK_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-${PACKAGE_PLATFORM_SUFFIX}")
ELSE()
SET(CPACK_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-${system_name}-${CMAKE_SYSTEM_PROCESSOR}")
ENDIF()
ELSE()
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-${PACKAGE_STATUS_SUFFIX}-src")
IF(PACKAGE_PLATFORM_SUFFIX)
SET(CPACK_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-${PACKAGE_STATUS_SUFFIX}-${PACKAGE_PLATFORM_SUFFIX}")
ELSE()
SET(CPACK_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-${PACKAGE_STATUS_SUFFIX}-${system_name}-${CMAKE_SYSTEM_PROCESSOR}")
ENDIF()
ENDIF()
# Build source packages
IF(GIT_BUILD_SRCPKG)
EXECUTE_PROCESS(
COMMAND ${GIT_EXECUTABLE} archive HEAD --format=zip
--prefix=${CPACK_SOURCE_PACKAGE_FILE_NAME}/
--output=${CPACK_SOURCE_PACKAGE_FILE_NAME}.zip)
IF(NOT WIN32)
EXECUTE_PROCESS(
COMMAND ${GIT_EXECUTABLE} archive HEAD --format=tar.gz
--prefix=${CPACK_SOURCE_PACKAGE_FILE_NAME}/
--output=${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.gz)
ENDIF()
ENDIF()
SET(CPACK_SOURCE_IGNORE_FILES
\\\\.git/
\\\\.gitignore
\\\\.gitattributes
CMakeCache\\\\.txt
cmake_dist\\\\.cmake
CPackConfig\\\\.cmake
mariadb_config\\\\.c$
\\\\.build/
html/
unittest
/cmake_install.cmake
/CTestTestfile.cmake
/CPackSourceConfig.cmake
/CMakeFiles/
/version_resources/
/_CPack_Packages/
\\\\.gz$
\\\\.zip$
mariadb_config/mariadb_config$
/CMakeFiles/
/version_resources/
/_CPack_Packages/
Makefile$
include/my_config\\\\.h$
)
IF(WITH_TEST_SRCPKG)
SET(PACKAGE_FILE ${CC_SOURCE_DIR}/package.name)
FILE(REMOVE ${PACKAGE_FILE})
FILE(WRITE ${PACKAGE_FILE} ${CPACK_SOURCE_PACKAGE_FILE_NAME})
ENDIF()
IF(WIN32)
SET(CPACK_GENERATOR "ZIP")
SET(CPACK_SOURCE_GENERATOR "ZIP")
ELSE()
SET(CPACK_GENERATOR "TGZ")
SET(CPACK_SOURCE_GENERATOR "TGZ")
ENDIF()
INCLUDE(CPack)
IF(WITH_EXTERNAL_ZLIB)
SET(zlib_status ${WITH_EXTERNAL_ZLIB})
ELSE()
SET(zlib_status "yes (using bundled zlib)")
ENDIF()
MESSAGE1(STATUS "MariaDB Connector/c configuration:
-- Static PLUGINS ${PLUGINS_STATIC}
-- Dynamic PLUGINS ${PLUGINS_DYNAMIC}
-- Disabled PLUGINS ${PLUGINS_DISABLED}
-- CPack generation: ${CPACK_GENERATOR}
-- SSL support: ${WITH_SSL} Libs: ${SSL_LIBRARIES}
-- Zlib support: ${zlib_status}
-- ZStd support: ${ZSTD_FOUND}
-- ASAN support: ${WITH_ASAN}
-- ASAN scope support: ${WITH_ASAN_SCOPE}
-- UBSAN support: ${WITH_UBSAN}
-- MSAN support: ${WITH_MSAN}
-- Installation layout: ${INSTALL_LAYOUT}
-- Include files will be installed in ${INSTALL_INCLUDEDIR}
-- Libraries will be installed in ${INSTALL_LIBDIR}
-- Binaries will be installed in ${INSTALL_BINDIR}
-- Required: ${CMAKE_REQUIRED_LIBRARIES}")

502
vendor/mariadb/COPYING.LIB vendored Normal file
View file

@ -0,0 +1,502 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

15
vendor/mariadb/README vendored Normal file
View file

@ -0,0 +1,15 @@
This is LGPL MariaDB client library that can be used to connect to a
MariaDB or MySQL database server.
This code is based on the LGPL libmysql client library from MySQL 3.23
and PHP's mysqlnd extension.
This product includes PHP software, freely available from
<http://www.php.net/software/>
If you want to be part of this development effort, you can discuss this at
maria-developers@lists.launchpad.org.
To report a bug you'll need to signup for an account at https://jira.mariadb.org
The MariaDB team

16
vendor/mariadb/appveyor-download.bat vendored Normal file
View file

@ -0,0 +1,16 @@
@echo off
set archive=http://ftp.hosteurope.de/mirror/archive.mariadb.org//mariadb-%DB%/winx64-packages/mariadb-%DB%-winx64.msi
set last=http://mirror.i3d.net/pub/mariadb//mariadb-%DB%/winx64-packages/mariadb-%DB%-winx64.msi
curl -fLsS -o server.msi %archive%
if %ERRORLEVEL% == 0 goto end
curl -fLsS -o server.msi %last%
if %ERRORLEVEL% == 0 goto end
echo Failure Reason Given is %errorlevel%
exit /b %errorlevel%
:end
echo "File found".

41
vendor/mariadb/appveyor.yml vendored Normal file
View file

@ -0,0 +1,41 @@
version: 3.0.8;{build}
branches:
only:
- 3.1
environment:
matrix:
- DB: '10.2.38'
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
CMAKE_PARAM: 'Visual Studio 15 2017 Win64'
- DB: '10.3.29'
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
CMAKE_PARAM: 'Visual Studio 15 2017 Win64'
- DB: '10.4.19'
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
CMAKE_PARAM: 'Visual Studio 15 2017 Win64'
- DB: '10.5.10'
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
CMAKE_PARAM: 'Visual Studio 15 2017 Win64'
configuration: RelWithDebInfo
clone_folder: c:\projects\mariadb-connector-c
before_build:
- cmd: appveyor-download.bat
- cmd: msiexec /i server.msi INSTALLDIR=c:\projects\server SERVICENAME=mariadb ALLOWREMOTEROOTACCESS=true /qn
- cmd: "\"c:\\projects\\server\\bin\\mysql.exe\" -e \"create database testc\" --user=root"
- cmd: set MARIADB_CC_TEST=1
- cmd: set MYSQL_TEST_USER=root
- cmd: set MYSQL_TEST_HOST=127.0.0.1
- cmd: set MYSQL_TEST_PASSWD=
- cmd: set MYSQL_TEST_PORT=3306
- cmd: set MYSQL_TEST_DB=testc
- cmd: cmake -G "%CMAKE_PARAM%" -DCMAKE_BUILD_TYPE=RelWithDebInfo
build:
project: mariadb-connector-c.sln
parallel: true
verbosity: minimal
test_script:
- cmd: cd c:\projects\mariadb-connector-c\unittest\libmariadb
- cmd: set MARIADB_PLUGIN_DIR=cd c:\projects\mariadb-connector-c\plugins\lib\RelWithDebInfo
- cmd: ctest -V

53
vendor/mariadb/benchmark/README.md vendored Normal file
View file

@ -0,0 +1,53 @@
# Benchmark MariaDB Connector/C
This permits to benchmark MariaDB C connector, along with MySQL connector
## Installation
To install google benchmark, mysql connector and build current connector :
```script
sudo benchmark/build.sh
cd benchmark
sudo ./installation.sh
```
## Basic run
This will runs the benchmark with 50 repetition to ensure stability then display results
```script
sudo ./launch.sh
```
## detailed benchmark
first ensure running cpu to maximum speed:
```script
sudo cpupower frequency-set --governor performance || true
```
default is benchmarking on one thread. adding benchmark on multiple thread can be done setting MAX_THREAD in main-benchmark.cc. Setting it to 256, benchmark will run on 1 to 256 threads.
Set server default environment with the following variables :
* TEST_DB_PORT (default 3306)
* TEST_DB_DATABASE (default "bench")
* TEST_DB_USER (default "root")
* TEST_DB_HOST (default "localhost")
* TEST_DB_PASSWORD
*
running with MariaDB driver:
```script
g++ main-benchmark.cc -std=c++11 -isystem benchmark/include -Lbenchmark/build/src -I/usr/local/include/mariadb -I/usr/local/include/mariadb/mysql -L/usr/local/lib/mariadb/ -lmariadb -lbenchmark -lpthread -o main-benchmark
./main-benchmark --benchmark_repetitions=10 --benchmark_time_unit=us --benchmark_min_warmup_time=10 --benchmark_counters_tabular=true --benchmark_format=json --benchmark_out=mariadb.json
```
running with MySQL driver:
```script
g++ main-benchmark.cc -std=c++11 -isystem benchmark/include -Lbenchmark/build/src -lbenchmark -lpthread -DBENCHMARK_MYSQL -lmysqlclient -o main-benchmark
./main-benchmark --benchmark_repetitions=10 --benchmark_time_unit=us --benchmark_min_warmup_time=10 --benchmark_counters_tabular=true --benchmark_format=json --benchmark_out=mysql.json
```
in order to compare results:
```script
pip3 install -r benchmark/requirements.txt
benchmark/tools/compare.py -a --no-utest benchmarksfiltered ./mysql.json MySQL ./mariadb.json MariaDB
```

19
vendor/mariadb/benchmark/build.sh vendored Executable file
View file

@ -0,0 +1,19 @@
#!/bin/bash
set -ex
mkdir bld
cd bld
sudo cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local
sudo cmake --build . --config Release --target install
sudo apt-get -f -y install linux-tools-common linux-gcp linux-tools-$(uname -r)
echo $LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/lib
sudo install /usr/local/lib/mariadb/libmariadb.so /usr/lib
sudo install -d /usr/lib/mariadb
sudo install -d /usr/lib/mariadb/plugin
sudo apt install libmysqlclient-dev

17
vendor/mariadb/benchmark/installation.sh vendored Executable file
View file

@ -0,0 +1,17 @@
#!/bin/bash
set -ex
# Check out the library.
git clone https://github.com/google/benchmark.git
# Go to the library root directory
cd benchmark
# Make a build directory to place the build output.
cmake -E make_directory "build"
# Generate build system files with cmake, and download any dependencies.
cmake -E chdir "build" cmake -DBENCHMARK_DOWNLOAD_DEPENDENCIES=on -DCMAKE_BUILD_TYPE=Release ../
# or, starting with CMake 3.13, use a simpler form:
# cmake -DCMAKE_BUILD_TYPE=Release -S . -B "build"
# Build the library.
cmake --build "build" --config Release

17
vendor/mariadb/benchmark/launch.sh vendored Executable file
View file

@ -0,0 +1,17 @@
#!/bin/bash
set -ex
sudo cpupower frequency-set --governor performance || true
g++ main-benchmark.cc -std=c++11 -isystem benchmark/include -Lbenchmark/build/src -I/usr/local/include/mariadb -I/usr/local/include/mariadb/mysql -L/usr/local/lib/mariadb/ -lmariadb -lbenchmark -lpthread -o main-benchmark
./main-benchmark --benchmark_repetitions=30 --benchmark_time_unit=us --benchmark_min_warmup_time=10 --benchmark_counters_tabular=true --benchmark_format=json --benchmark_out=mariadb.json
g++ main-benchmark.cc -std=c++11 -isystem benchmark/include -Lbenchmark/build/src -lbenchmark -lpthread -DBENCHMARK_MYSQL -lmysqlclient -o main-benchmark
./main-benchmark --benchmark_repetitions=30 --benchmark_time_unit=us --benchmark_min_warmup_time=10 --benchmark_counters_tabular=true --benchmark_format=json --benchmark_out=mysql.json
pip3 install -r benchmark/requirements.txt
benchmark/tools/compare.py -a --no-utest benchmarksfiltered ./mysql.json MySQL ./mariadb.json MariaDB

View file

@ -0,0 +1,556 @@
#include <benchmark/benchmark.h>
#include <iostream>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <stdio.h>
const int MAX_THREAD = 1;
#define OPERATION_PER_SECOND_LABEL "nb operations per second"
std::string GetEnvironmentVariableOrDefault(const std::string& variable_name,
const std::string& default_value)
{
const char* value = getenv(variable_name.c_str());
return value ? value : default_value;
}
std::string DB_PORT = GetEnvironmentVariableOrDefault("TEST_DB_PORT", "3306");
std::string DB_DATABASE = GetEnvironmentVariableOrDefault("TEST_DB_DATABASE", "bench");
std::string DB_USER = GetEnvironmentVariableOrDefault("TEST_DB_USER", "root");
std::string DB_HOST = GetEnvironmentVariableOrDefault("TEST_DB_HOST", "127.0.0.1");
std::string DB_PASSWORD = GetEnvironmentVariableOrDefault("TEST_DB_PASSWORD", "");
#define check_conn_rc(rc, mysql) \
do {\
if (rc)\
{\
fprintf(stdout,"Error (%d): %s (%d) in %s line %d", rc, mysql_error(mysql), \
mysql_errno(mysql), __FILE__, __LINE__);\
mysql_close(conn);\
exit(1);\
}\
} while(0)
#define check_stmt_rc(rc, stmt, mysql) \
do {\
if (rc)\
{\
fprintf(stdout,"Error (%d): %d (%s) in %s line %d", rc, mysql_stmt_errno(stmt), \
mysql_stmt_error(stmt), __FILE__, __LINE__);\
mysql_close(conn);\
exit(1);\
}\
} while(0)
#ifndef BENCHMARK_MYSQL
#include <mysql.h>
const std::string TYPE = "MariaDB";
MYSQL* connect(std::string options) {
MYSQL *con = mysql_init(NULL);
if (!(con = mysql_init(0))) {
fprintf(stderr, "unable to initialize connection struct\n");
exit(1);
}
enum mysql_protocol_type prot_type= MYSQL_PROTOCOL_TCP;
mysql_optionsv(con, MYSQL_OPT_PROTOCOL, (void *)&prot_type);
if (mysql_real_connect(con, DB_HOST.c_str(), DB_USER.c_str(), DB_PASSWORD.c_str(),
DB_DATABASE.c_str(), atoi(DB_PORT.c_str()), NULL, 0) == NULL) {
fprintf(stderr, "%s\n", mysql_error(con));
mysql_close(con);
exit(1);
}
return con;
}
#endif
#ifdef BENCHMARK_MYSQL
#include <mysql/mysql.h>
const std::string TYPE = "MySQL";
MYSQL* connect(std::string options) {
MYSQL *con = mysql_init(NULL);
if (con == NULL) {
fprintf(stderr, "%s\n", mysql_error(con));
exit(1);
}
enum mysql_protocol_type prot_type= MYSQL_PROTOCOL_TCP;
mysql_options(con, MYSQL_OPT_PROTOCOL, (void *)&prot_type);
if (mysql_real_connect(con, DB_HOST.c_str(), DB_USER.c_str(), DB_PASSWORD.c_str(),
DB_DATABASE.c_str(), atoi(DB_PORT.c_str()), NULL, 0) == NULL) {
fprintf(stderr, "%s\n", mysql_error(con));
mysql_close(con);
exit(1);
}
return con;
}
#endif
void do_1(benchmark::State& state, MYSQL* conn) {
int rc;
rc = mysql_query(conn, "DO 1");
check_conn_rc(rc, conn);
int id;
benchmark::DoNotOptimize(id = mysql_insert_id(conn));
}
static void BM_DO_1(benchmark::State& state) {
MYSQL *conn = connect("");
int numOperation = 0;
for (auto _ : state) {
do_1(state, conn);
numOperation++;
}
state.counters[OPERATION_PER_SECOND_LABEL] = benchmark::Counter(numOperation, benchmark::Counter::kIsRate);
mysql_close(conn);
}
BENCHMARK(BM_DO_1)->Name(TYPE + " DO 1")->ThreadRange(1, MAX_THREAD)->UseRealTime();
void select_1(benchmark::State& state, MYSQL* conn) {
int rc;
rc = mysql_query(conn, "SELECT 1");
check_conn_rc(rc, conn);
MYSQL_RES *result = mysql_store_result(conn);
int num_fields = mysql_num_fields(result);
char* val_name;
MYSQL_FIELD *field;
while(field = mysql_fetch_field(result)) {
benchmark::DoNotOptimize(val_name = field->name);
}
int val;
MYSQL_ROW row;
while ((row = mysql_fetch_row(result))) {
for(int i = 0; i < num_fields; i++) {
benchmark::DoNotOptimize(val = atoi(row[i]));
}
}
mysql_free_result(result);
}
static void BM_SELECT_1(benchmark::State& state) {
MYSQL *conn = connect("");
int numOperation = 0;
for (auto _ : state) {
select_1(state, conn);
numOperation++;
}
state.counters[OPERATION_PER_SECOND_LABEL] = benchmark::Counter(numOperation, benchmark::Counter::kIsRate);
mysql_close(conn);
}
BENCHMARK(BM_SELECT_1)->Name(TYPE + " SELECT 1")->ThreadRange(1, MAX_THREAD)->UseRealTime();
void select_1000_rows(benchmark::State& state, MYSQL* conn) {
if (mysql_query(conn, "select seq, 'abcdefghijabcdefghijabcdefghijaa' from seq_1_to_1000")) {
fprintf(stderr, "%s\n", mysql_error(conn));
mysql_close(conn);
exit(1);
}
MYSQL_RES *result = mysql_store_result(conn);
unsigned int num_fields = mysql_num_fields(result);
if (result == NULL) {
fprintf(stderr, "%s\n", mysql_error(conn));
mysql_close(conn);
exit(1);
}
int val1;
std::string val2;
MYSQL_ROW row;
while ((row = mysql_fetch_row(result))) {
benchmark::DoNotOptimize(val1 = atoi(row[0]));
benchmark::DoNotOptimize(val2 = row[1]);
benchmark::ClobberMemory();
}
mysql_free_result(result);
}
static void BM_SELECT_1000_ROWS(benchmark::State& state) {
MYSQL *conn = connect("");
int numOperation = 0;
for (auto _ : state) {
select_1000_rows(state, conn);
numOperation++;
}
state.counters[OPERATION_PER_SECOND_LABEL] = benchmark::Counter(numOperation, benchmark::Counter::kIsRate);
mysql_close(conn);
}
BENCHMARK(BM_SELECT_1000_ROWS)->Name(TYPE + " SELECT 1000 rows (int + char(32))")->ThreadRange(1, MAX_THREAD)->UseRealTime();
static void setup_select_100_int_cols(const benchmark::State& state) {
MYSQL *conn = connect("");
int rc;
rc = mysql_query(conn, "DROP TABLE IF EXISTS test100");
check_conn_rc(rc, conn);
rc = mysql_query(conn, "CREATE TABLE test100 (i1 int,i2 int,i3 int,i4 int,i5 int,i6 int,i7 int,i8 int,i9 int,i10 int,i11 int,i12 int,i13 int,i14 int,i15 int,i16 int,i17 int,i18 int,i19 int,i20 int,i21 int,i22 int,i23 int,i24 int,i25 int,i26 int,i27 int,i28 int,i29 int,i30 int,i31 int,i32 int,i33 int,i34 int,i35 int,i36 int,i37 int,i38 int,i39 int,i40 int,i41 int,i42 int,i43 int,i44 int,i45 int,i46 int,i47 int,i48 int,i49 int,i50 int,i51 int,i52 int,i53 int,i54 int,i55 int,i56 int,i57 int,i58 int,i59 int,i60 int,i61 int,i62 int,i63 int,i64 int,i65 int,i66 int,i67 int,i68 int,i69 int,i70 int,i71 int,i72 int,i73 int,i74 int,i75 int,i76 int,i77 int,i78 int,i79 int,i80 int,i81 int,i82 int,i83 int,i84 int,i85 int,i86 int,i87 int,i88 int,i89 int,i90 int,i91 int,i92 int,i93 int,i94 int,i95 int,i96 int,i97 int,i98 int,i99 int,i100 int)");
check_conn_rc(rc, conn);
rc = mysql_query(conn, "INSERT INTO test100 value (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100)");
check_conn_rc(rc, conn);
mysql_close(conn);
}
void select_100_int_cols(benchmark::State& state, MYSQL* conn) {
int rc;
rc = mysql_query(conn, "select * FROM test100");
check_conn_rc(rc, conn);
MYSQL_RES *result = mysql_store_result(conn);
unsigned int num_fields = mysql_num_fields(result);
if (result == NULL) {
fprintf(stderr, "%s\n", mysql_error(conn));
mysql_close(conn);
exit(1);
}
int val1;
MYSQL_ROW row;
while ((row = mysql_fetch_row(result))) {
for (int i=0; i<100; i++)
benchmark::DoNotOptimize(val1 = atoi(row[i]));
benchmark::ClobberMemory();
}
mysql_free_result(result);
}
void select_100_int_cols_with_prepare(benchmark::State& state, MYSQL* conn) {
MYSQL_STMT *stmt = mysql_stmt_init(conn);
std::string query = "select * FROM test100";
int rc;
rc = mysql_stmt_prepare(stmt, query.c_str(), (unsigned long)query.size());
check_conn_rc(rc, conn);
int int_data[100];
unsigned long length[100];
MYSQL_BIND my_bind[100];
memset(my_bind, 0, sizeof(my_bind));
for (int i = 0; i < 100; i++) {
my_bind[i].buffer_type= MYSQL_TYPE_LONG;
my_bind[i].buffer= (char *) &int_data[i];
my_bind[i].length= &length[i];
}
rc = mysql_stmt_execute(stmt);
check_conn_rc(rc, conn);
rc = mysql_stmt_bind_result(stmt, my_bind);
check_stmt_rc(rc, stmt, conn);
rc = mysql_stmt_store_result(stmt);
check_stmt_rc(rc, stmt, conn);
while (mysql_stmt_fetch(stmt)) {
//
}
mysql_stmt_close(stmt);
}
void select_100_int_cols_prepared(benchmark::State& state, MYSQL* conn, MYSQL_STMT* stmt) {
int rc;
int int_data[100];
unsigned long length[100];
MYSQL_BIND my_bind[100];
memset(my_bind, 0, sizeof(my_bind));
for (int i = 0; i < 100; i++) {
my_bind[i].buffer_type= MYSQL_TYPE_LONG;
my_bind[i].buffer= (char *) &int_data[i];
my_bind[i].length= &length[i];
}
rc = mysql_stmt_execute(stmt);
check_conn_rc(rc, conn);
rc = mysql_stmt_bind_result(stmt, my_bind);
check_stmt_rc(rc, stmt, conn);
rc = mysql_stmt_store_result(stmt);
check_stmt_rc(rc, stmt, conn);
while (mysql_stmt_fetch(stmt)) {
//
}
}
static void BM_SELECT_100_INT_COLS(benchmark::State& state) {
MYSQL *conn = connect("");
int numOperation = 0;
for (auto _ : state) {
select_100_int_cols(state, conn);
numOperation++;
}
state.counters[OPERATION_PER_SECOND_LABEL] = benchmark::Counter(numOperation, benchmark::Counter::kIsRate);
mysql_close(conn);
}
static void BM_SELECT_100_INT_COLS_WITH_PREPARE(benchmark::State& state) {
MYSQL *conn = connect("");
int numOperation = 0;
for (auto _ : state) {
select_100_int_cols_with_prepare(state, conn);
numOperation++;
}
state.counters[OPERATION_PER_SECOND_LABEL] = benchmark::Counter(numOperation, benchmark::Counter::kIsRate);
mysql_close(conn);
}
static void BM_SELECT_100_INT_COLS_PREPARED(benchmark::State& state) {
MYSQL *conn = connect("");
MYSQL_STMT *stmt = mysql_stmt_init(conn);
std::string query = "select * FROM test100";
int rc;
rc = mysql_stmt_prepare(stmt, query.c_str(), (unsigned long)query.size());
check_conn_rc(rc, conn);
int numOperation = 0;
for (auto _ : state) {
select_100_int_cols_prepared(state, conn, stmt);
numOperation++;
}
state.counters[OPERATION_PER_SECOND_LABEL] = benchmark::Counter(numOperation, benchmark::Counter::kIsRate);
mysql_stmt_close(stmt);
mysql_close(conn);
}
BENCHMARK(BM_SELECT_100_INT_COLS)->Name(TYPE + " SELECT 100 int cols")->ThreadRange(1, MAX_THREAD)->UseRealTime()->Setup(setup_select_100_int_cols);
BENCHMARK(BM_SELECT_100_INT_COLS_WITH_PREPARE)->Name(TYPE + " SELECT 100 int cols - BINARY prepare+execute+close")->ThreadRange(1, MAX_THREAD)->UseRealTime();
BENCHMARK(BM_SELECT_100_INT_COLS_PREPARED)->Name(TYPE + " SELECT 100 int cols - BINARY execute only")->ThreadRange(1, MAX_THREAD)->UseRealTime();
void do_1000_params(benchmark::State& state, MYSQL* conn, const char* query) {
int rc;
rc = mysql_query(conn, query);
check_conn_rc(rc, conn);
int id;
benchmark::DoNotOptimize(id = mysql_insert_id(conn));
}
static void BM_DO_1000_PARAMS(benchmark::State& state) {
MYSQL *conn = connect("");
std::string query = "DO 1";
for (int i = 1; i < 1000; i++) {
query += "," + std::to_string(i);
}
const char* queryChar = query.c_str();
int rc;
int numOperation = 0;
for (auto _ : state) {
do_1000_params(state, conn, queryChar);
numOperation++;
}
state.counters[OPERATION_PER_SECOND_LABEL] = benchmark::Counter(numOperation, benchmark::Counter::kIsRate);
mysql_close(conn);
}
BENCHMARK(BM_DO_1000_PARAMS)->Name(TYPE + " DO 1000 params")->ThreadRange(1, MAX_THREAD)->UseRealTime();
static void setup_insert_batch(const benchmark::State& state) {
MYSQL *conn = connect("");
int rc;
rc = mysql_query(conn, "DROP TABLE IF EXISTS perfTestTextBatch");
check_conn_rc(rc, conn);
rc = mysql_query(conn, "INSTALL SONAME 'ha_blackhole'");
rc = mysql_query(conn, "CREATE TABLE perfTestTextBatch (id MEDIUMINT NOT NULL AUTO_INCREMENT,t0 text, PRIMARY KEY (id)) COLLATE='utf8mb4_unicode_ci' ENGINE = BLACKHOLE");
if (rc) {
rc = mysql_query(conn, "CREATE TABLE perfTestTextBatch (id MEDIUMINT NOT NULL AUTO_INCREMENT,t0 text, PRIMARY KEY (id)) COLLATE='utf8mb4_unicode_ci'");
check_conn_rc(rc, conn);
}
mysql_close(conn);
}
std::vector<std::string> chars = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "\\Z", "😎", "🌶", "🎤", "🥂" };
std::string randomString(int length) {
std::string result = "";
for (int i = length; i > 0; --i) {
result += chars[rand() % (chars.size() - 1)];
}
return result;
}
void insert_batch_with_prepare(benchmark::State& state, MYSQL* conn) {
MYSQL_STMT *stmt = mysql_stmt_init(conn);
std::string query = "INSERT INTO perfTestTextBatch(t0) VALUES (?)";
int rc;
rc = mysql_stmt_prepare(stmt, query.c_str(), (unsigned long)query.size());
check_conn_rc(rc, conn);
std::string randomStringVal = randomString(100);
char* randValue = (char *)randomStringVal.c_str();
long unsigned randValueLen = randomStringVal.length();
MYSQL_BIND my_bind[1];
memset(my_bind, 0, sizeof(my_bind));
my_bind[0].buffer_type= MYSQL_TYPE_STRING;
my_bind[0].buffer= randValue;
my_bind[0].length= &randValueLen;
for (int i = 0; i < 100; i++) {
rc = mysql_stmt_bind_param(stmt, my_bind);
check_stmt_rc(rc, stmt, conn);
rc = mysql_stmt_execute(stmt);
check_conn_rc(rc, conn);
}
mysql_stmt_close(stmt);
}
static void BM_INSERT_BATCH_WITH_PREPARE(benchmark::State& state) {
MYSQL *conn = connect("");
int numOperation = 0;
for (auto _ : state) {
insert_batch_with_prepare(state, conn);
numOperation++;
}
state.counters[OPERATION_PER_SECOND_LABEL] = benchmark::Counter(numOperation, benchmark::Counter::kIsRate);
mysql_close(conn);
}
BENCHMARK(BM_INSERT_BATCH_WITH_PREPARE)->Name(TYPE + " insert batch looping execute")->ThreadRange(1, MAX_THREAD)->UseRealTime()->Setup(setup_insert_batch);
#ifndef BENCHMARK_MYSQL
void insert_bulk_batch_with_prepare(benchmark::State& state, MYSQL* conn, MYSQL_STMT *stmt) {
int rc;
std::string randomStringVal = randomString(100);
char* randValue = (char *)randomStringVal.c_str();
long randValueLen = randomStringVal.length();
unsigned int numrows = 100;
long unsigned value_len[100];
char *valueptr[100];
for (int i = 0; i < 100; i++) {
valueptr[i]= randValue;
value_len[i]= randValueLen;
}
MYSQL_BIND my_bind[1];
memset(my_bind, 0, sizeof(my_bind));
my_bind[0].u.indicator = 0;
my_bind[0].buffer_type= MYSQL_TYPE_STRING;
my_bind[0].buffer= valueptr;
my_bind[0].length= value_len;
rc = mysql_stmt_bind_param(stmt, my_bind);
check_stmt_rc(rc, stmt, conn);
mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &numrows);
rc = mysql_stmt_execute(stmt);
check_conn_rc(rc, conn);
}
static void BM_INSERT_BULK_BATCH_WITH_PREPARE(benchmark::State& state) {
MYSQL *conn = connect("");
MYSQL_STMT *stmt = mysql_stmt_init(conn);
std::string query = "INSERT INTO perfTestTextBatch(t0) VALUES (?)";
int rc;
rc = mysql_stmt_prepare(stmt, query.c_str(), (unsigned long)query.size());
check_conn_rc(rc, conn);
int numOperation = 0;
for (auto _ : state) {
insert_bulk_batch_with_prepare(state, conn, stmt);
numOperation++;
}
state.counters[OPERATION_PER_SECOND_LABEL] = benchmark::Counter(numOperation, benchmark::Counter::kIsRate);
mysql_stmt_close(stmt);
mysql_close(conn);
}
BENCHMARK(BM_INSERT_BULK_BATCH_WITH_PREPARE)->Name(TYPE + " insert batch using bulk")->ThreadRange(1, MAX_THREAD)->UseRealTime()->Setup(setup_insert_batch);
void select_100_int_cols_with_prepare_pipeline(benchmark::State& state, MYSQL* conn) {
MYSQL_STMT *stmt = mysql_stmt_init(conn);
std::string query = "select * FROM test100";
int rc;
int int_data[100];
unsigned long length[100];
MYSQL_BIND my_bind[100];
memset(my_bind, 0, sizeof(my_bind));
for (int i = 0; i < 100; i++) {
my_bind[i].buffer_type= MYSQL_TYPE_LONG;
my_bind[i].buffer= (char *) &int_data[i];
my_bind[i].length= &length[i];
}
rc = mariadb_stmt_execute_direct(stmt, query.c_str(), (unsigned long)query.size());
check_conn_rc(rc, conn);
rc = mysql_stmt_bind_result(stmt, my_bind);
check_stmt_rc(rc, stmt, conn);
rc = mysql_stmt_store_result(stmt);
check_stmt_rc(rc, stmt, conn);
while (mysql_stmt_fetch(stmt)) {
//
}
mysql_stmt_close(stmt);
}
static void BM_SELECT_100_INT_COLS_WITH_PREPARE_PIPELINE(benchmark::State& state) {
MYSQL *conn = connect("");
int numOperation = 0;
for (auto _ : state) {
select_100_int_cols_with_prepare_pipeline(state, conn);
numOperation++;
}
state.counters[OPERATION_PER_SECOND_LABEL] = benchmark::Counter(numOperation, benchmark::Counter::kIsRate);
mysql_close(conn);
}
BENCHMARK(BM_SELECT_100_INT_COLS_WITH_PREPARE_PIPELINE)->Name(TYPE + " SELECT 100 int cols - BINARY pipeline prepare+execute+close")->ThreadRange(1, MAX_THREAD)->UseRealTime()->Setup(setup_insert_batch);
#endif
BENCHMARK_MAIN();

69
vendor/mariadb/build/CPackConfig.cmake vendored Normal file
View file

@ -0,0 +1,69 @@
# This file will be configured to contain variables for CPack. These variables
# should be set in the CMake list file of the project before CPack module is
# included. The list of available CPACK_xxx variables and their associated
# documentation may be obtained using
# cpack --help-variable-list
#
# Some variables are common to all generators (e.g. CPACK_PACKAGE_NAME)
# and some are specific to a generator
# (e.g. CPACK_NSIS_EXTRA_INSTALL_COMMANDS). The generator specific variables
# usually begin with CPACK_<GENNAME>_xxxx.
set(CPACK_BUILD_SOURCE_DIRS "/home/scott/claude/calog/vendor/mariadb;/home/scott/claude/calog/vendor/mariadb/build")
set(CPACK_CMAKE_GENERATOR "Unix Makefiles")
set(CPACK_COMPONENTS_ALL "ClientPlugins;Development;ManPagesDevelopment;SharedLibraries")
set(CPACK_COMPONENT_UNSPECIFIED_HIDDEN "TRUE")
set(CPACK_COMPONENT_UNSPECIFIED_REQUIRED "TRUE")
set(CPACK_DEFAULT_PACKAGE_DESCRIPTION_FILE "/usr/share/cmake-3.28/Templates/CPack.GenericDescription.txt")
set(CPACK_DEFAULT_PACKAGE_DESCRIPTION_SUMMARY "mariadb-connector-c built using CMake")
set(CPACK_DMG_SLA_USE_RESOURCE_FILE_LICENSE "ON")
set(CPACK_GENERATOR "TGZ")
set(CPACK_INNOSETUP_ARCHITECTURE "x64")
set(CPACK_INSTALL_CMAKE_PROJECTS "/home/scott/claude/calog/vendor/mariadb/build;mariadb-connector-c;ALL;/")
set(CPACK_INSTALL_PREFIX "/usr/local")
set(CPACK_MODULE_PATH "")
set(CPACK_NSIS_DISPLAY_NAME "mariadb_connector_c 3.4.10")
set(CPACK_NSIS_INSTALLER_ICON_CODE "")
set(CPACK_NSIS_INSTALLER_MUI_ICON_CODE "")
set(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES")
set(CPACK_NSIS_PACKAGE_NAME "mariadb_connector_c 3.4.10")
set(CPACK_NSIS_UNINSTALL_NAME "Uninstall")
set(CPACK_OBJCOPY_EXECUTABLE "/usr/bin/objcopy")
set(CPACK_OBJDUMP_EXECUTABLE "/usr/bin/objdump")
set(CPACK_OUTPUT_CONFIG_FILE "/home/scott/claude/calog/vendor/mariadb/build/CPackConfig.cmake")
set(CPACK_PACKAGE_DEFAULT_LOCATION "/")
set(CPACK_PACKAGE_DESCRIPTION "MariaDB Connector/C. A library for connecting to MariaDB and MySQL servers")
set(CPACK_PACKAGE_DESCRIPTION_FILE "/home/scott/claude/calog/vendor/mariadb/README")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "mariadb-connector-c built using CMake")
set(CPACK_PACKAGE_FILE_NAME "mariadb-connector-c-3.4.10-linux-x86_64")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "mariadb_connector_c 3.4.10")
set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "mariadb_connector_c 3.4.10")
set(CPACK_PACKAGE_NAME "mariadb_connector_c")
set(CPACK_PACKAGE_RELOCATABLE "true")
set(CPACK_PACKAGE_VENDOR "MariaDB Corporation Ab")
set(CPACK_PACKAGE_VERSION "3.4.10")
set(CPACK_PACKAGE_VERSION_MAJOR "3")
set(CPACK_PACKAGE_VERSION_MINOR "4")
set(CPACK_PACKAGE_VERSION_PATCH "10")
set(CPACK_READELF_EXECUTABLE "/usr/bin/readelf")
set(CPACK_RESOURCE_FILE_LICENSE "/home/scott/claude/calog/vendor/mariadb/COPYING.LIB")
set(CPACK_RESOURCE_FILE_README "/usr/share/cmake-3.28/Templates/CPack.GenericDescription.txt")
set(CPACK_RESOURCE_FILE_WELCOME "/usr/share/cmake-3.28/Templates/CPack.GenericWelcome.txt")
set(CPACK_SET_DESTDIR "OFF")
set(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_SOURCE_IGNORE_FILES "\\.git/;\\.gitignore;\\.gitattributes;CMakeCache\\.txt;cmake_dist\\.cmake;CPackConfig\\.cmake;mariadb_config\\.c$;\\.build/;html/;unittest;/cmake_install.cmake;/CTestTestfile.cmake;/CPackSourceConfig.cmake;/CMakeFiles/;/version_resources/;/_CPack_Packages/;\\.gz$;\\.zip$;mariadb_config/mariadb_config$;/CMakeFiles/;/version_resources/;/_CPack_Packages/;Makefile$;include/my_config\\.h$")
set(CPACK_SOURCE_OUTPUT_CONFIG_FILE "/home/scott/claude/calog/vendor/mariadb/build/CPackSourceConfig.cmake")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "mariadb-connector-c-3.4.10-src")
set(CPACK_SYSTEM_NAME "Linux")
set(CPACK_THREADS "1")
set(CPACK_TOPLEVEL_TAG "Linux")
set(CPACK_WIX_SIZEOF_VOID_P "8")
if(NOT CPACK_PROPERTIES_FILE)
set(CPACK_PROPERTIES_FILE "/home/scott/claude/calog/vendor/mariadb/build/CPackProperties.cmake")
endif()
if(EXISTS ${CPACK_PROPERTIES_FILE})
include(${CPACK_PROPERTIES_FILE})
endif()

View file

@ -0,0 +1,75 @@
# This file will be configured to contain variables for CPack. These variables
# should be set in the CMake list file of the project before CPack module is
# included. The list of available CPACK_xxx variables and their associated
# documentation may be obtained using
# cpack --help-variable-list
#
# Some variables are common to all generators (e.g. CPACK_PACKAGE_NAME)
# and some are specific to a generator
# (e.g. CPACK_NSIS_EXTRA_INSTALL_COMMANDS). The generator specific variables
# usually begin with CPACK_<GENNAME>_xxxx.
set(CPACK_BUILD_SOURCE_DIRS "/home/scott/claude/calog/vendor/mariadb;/home/scott/claude/calog/vendor/mariadb/build")
set(CPACK_CMAKE_GENERATOR "Unix Makefiles")
set(CPACK_COMPONENTS_ALL "ClientPlugins;Development;ManPagesDevelopment;SharedLibraries")
set(CPACK_COMPONENT_UNSPECIFIED_HIDDEN "TRUE")
set(CPACK_COMPONENT_UNSPECIFIED_REQUIRED "TRUE")
set(CPACK_DEFAULT_PACKAGE_DESCRIPTION_FILE "/usr/share/cmake-3.28/Templates/CPack.GenericDescription.txt")
set(CPACK_DEFAULT_PACKAGE_DESCRIPTION_SUMMARY "mariadb-connector-c built using CMake")
set(CPACK_DMG_SLA_USE_RESOURCE_FILE_LICENSE "ON")
set(CPACK_GENERATOR "TGZ")
set(CPACK_IGNORE_FILES "\\.git/;\\.gitignore;\\.gitattributes;CMakeCache\\.txt;cmake_dist\\.cmake;CPackConfig\\.cmake;mariadb_config\\.c$;\\.build/;html/;unittest;/cmake_install.cmake;/CTestTestfile.cmake;/CPackSourceConfig.cmake;/CMakeFiles/;/version_resources/;/_CPack_Packages/;\\.gz$;\\.zip$;mariadb_config/mariadb_config$;/CMakeFiles/;/version_resources/;/_CPack_Packages/;Makefile$;include/my_config\\.h$")
set(CPACK_INNOSETUP_ARCHITECTURE "x64")
set(CPACK_INSTALLED_DIRECTORIES "/home/scott/claude/calog/vendor/mariadb;/")
set(CPACK_INSTALL_CMAKE_PROJECTS "")
set(CPACK_INSTALL_PREFIX "/usr/local")
set(CPACK_MODULE_PATH "")
set(CPACK_NSIS_DISPLAY_NAME "mariadb_connector_c 3.4.10")
set(CPACK_NSIS_INSTALLER_ICON_CODE "")
set(CPACK_NSIS_INSTALLER_MUI_ICON_CODE "")
set(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES")
set(CPACK_NSIS_PACKAGE_NAME "mariadb_connector_c 3.4.10")
set(CPACK_NSIS_UNINSTALL_NAME "Uninstall")
set(CPACK_OBJCOPY_EXECUTABLE "/usr/bin/objcopy")
set(CPACK_OBJDUMP_EXECUTABLE "/usr/bin/objdump")
set(CPACK_OUTPUT_CONFIG_FILE "/home/scott/claude/calog/vendor/mariadb/build/CPackConfig.cmake")
set(CPACK_PACKAGE_DEFAULT_LOCATION "/")
set(CPACK_PACKAGE_DESCRIPTION "MariaDB Connector/C. A library for connecting to MariaDB and MySQL servers")
set(CPACK_PACKAGE_DESCRIPTION_FILE "/home/scott/claude/calog/vendor/mariadb/README")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "mariadb-connector-c built using CMake")
set(CPACK_PACKAGE_FILE_NAME "mariadb-connector-c-3.4.10-src")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "mariadb_connector_c 3.4.10")
set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "mariadb_connector_c 3.4.10")
set(CPACK_PACKAGE_NAME "mariadb_connector_c")
set(CPACK_PACKAGE_RELOCATABLE "true")
set(CPACK_PACKAGE_VENDOR "MariaDB Corporation Ab")
set(CPACK_PACKAGE_VERSION "3.4.10")
set(CPACK_PACKAGE_VERSION_MAJOR "3")
set(CPACK_PACKAGE_VERSION_MINOR "4")
set(CPACK_PACKAGE_VERSION_PATCH "10")
set(CPACK_READELF_EXECUTABLE "/usr/bin/readelf")
set(CPACK_RESOURCE_FILE_LICENSE "/home/scott/claude/calog/vendor/mariadb/COPYING.LIB")
set(CPACK_RESOURCE_FILE_README "/usr/share/cmake-3.28/Templates/CPack.GenericDescription.txt")
set(CPACK_RESOURCE_FILE_WELCOME "/usr/share/cmake-3.28/Templates/CPack.GenericWelcome.txt")
set(CPACK_RPM_PACKAGE_SOURCES "ON")
set(CPACK_SET_DESTDIR "OFF")
set(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_SOURCE_IGNORE_FILES "\\.git/;\\.gitignore;\\.gitattributes;CMakeCache\\.txt;cmake_dist\\.cmake;CPackConfig\\.cmake;mariadb_config\\.c$;\\.build/;html/;unittest;/cmake_install.cmake;/CTestTestfile.cmake;/CPackSourceConfig.cmake;/CMakeFiles/;/version_resources/;/_CPack_Packages/;\\.gz$;\\.zip$;mariadb_config/mariadb_config$;/CMakeFiles/;/version_resources/;/_CPack_Packages/;Makefile$;include/my_config\\.h$")
set(CPACK_SOURCE_INSTALLED_DIRECTORIES "/home/scott/claude/calog/vendor/mariadb;/")
set(CPACK_SOURCE_OUTPUT_CONFIG_FILE "/home/scott/claude/calog/vendor/mariadb/build/CPackSourceConfig.cmake")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "mariadb-connector-c-3.4.10-src")
set(CPACK_SOURCE_TOPLEVEL_TAG "Linux-Source")
set(CPACK_STRIP_FILES "")
set(CPACK_SYSTEM_NAME "Linux")
set(CPACK_THREADS "1")
set(CPACK_TOPLEVEL_TAG "Linux-Source")
set(CPACK_WIX_SIZEOF_VOID_P "8")
if(NOT CPACK_PROPERTIES_FILE)
set(CPACK_PROPERTIES_FILE "/home/scott/claude/calog/vendor/mariadb/build/CPackProperties.cmake")
endif()
if(EXISTS ${CPACK_PROPERTIES_FILE})
include(${CPACK_PROPERTIES_FILE})
endif()

View file

@ -0,0 +1,545 @@
/* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#ifndef ZCONF_H
#define ZCONF_H
/* #undef Z_PREFIX */
#define Z_HAVE_UNISTD_H
/*
* If you *really* need a unique prefix for all types and library functions,
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
* Even better than compiling with -DZ_PREFIX would be to use configure to set
* this permanently in zconf.h using "./configure --zprefix".
*/
#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
# define Z_PREFIX_SET
/* all linked symbols and init macros */
# define _dist_code z__dist_code
# define _length_code z__length_code
# define _tr_align z__tr_align
# define _tr_flush_bits z__tr_flush_bits
# define _tr_flush_block z__tr_flush_block
# define _tr_init z__tr_init
# define _tr_stored_block z__tr_stored_block
# define _tr_tally z__tr_tally
# define adler32 z_adler32
# define adler32_combine z_adler32_combine
# define adler32_combine64 z_adler32_combine64
# define adler32_z z_adler32_z
# ifndef Z_SOLO
# define compress z_compress
# define compress2 z_compress2
# define compressBound z_compressBound
# endif
# define crc32 z_crc32
# define crc32_combine z_crc32_combine
# define crc32_combine64 z_crc32_combine64
# define crc32_combine_gen z_crc32_combine_gen
# define crc32_combine_gen64 z_crc32_combine_gen64
# define crc32_combine_op z_crc32_combine_op
# define crc32_z z_crc32_z
# define deflate z_deflate
# define deflateBound z_deflateBound
# define deflateCopy z_deflateCopy
# define deflateEnd z_deflateEnd
# define deflateGetDictionary z_deflateGetDictionary
# define deflateInit z_deflateInit
# define deflateInit2 z_deflateInit2
# define deflateInit2_ z_deflateInit2_
# define deflateInit_ z_deflateInit_
# define deflateParams z_deflateParams
# define deflatePending z_deflatePending
# define deflatePrime z_deflatePrime
# define deflateReset z_deflateReset
# define deflateResetKeep z_deflateResetKeep
# define deflateSetDictionary z_deflateSetDictionary
# define deflateSetHeader z_deflateSetHeader
# define deflateTune z_deflateTune
# define deflate_copyright z_deflate_copyright
# define get_crc_table z_get_crc_table
# ifndef Z_SOLO
# define gz_error z_gz_error
# define gz_intmax z_gz_intmax
# define gz_strwinerror z_gz_strwinerror
# define gzbuffer z_gzbuffer
# define gzclearerr z_gzclearerr
# define gzclose z_gzclose
# define gzclose_r z_gzclose_r
# define gzclose_w z_gzclose_w
# define gzdirect z_gzdirect
# define gzdopen z_gzdopen
# define gzeof z_gzeof
# define gzerror z_gzerror
# define gzflush z_gzflush
# define gzfread z_gzfread
# define gzfwrite z_gzfwrite
# define gzgetc z_gzgetc
# define gzgetc_ z_gzgetc_
# define gzgets z_gzgets
# define gzoffset z_gzoffset
# define gzoffset64 z_gzoffset64
# define gzopen z_gzopen
# define gzopen64 z_gzopen64
# ifdef _WIN32
# define gzopen_w z_gzopen_w
# endif
# define gzprintf z_gzprintf
# define gzputc z_gzputc
# define gzputs z_gzputs
# define gzread z_gzread
# define gzrewind z_gzrewind
# define gzseek z_gzseek
# define gzseek64 z_gzseek64
# define gzsetparams z_gzsetparams
# define gztell z_gztell
# define gztell64 z_gztell64
# define gzungetc z_gzungetc
# define gzvprintf z_gzvprintf
# define gzwrite z_gzwrite
# endif
# define inflate z_inflate
# define inflateBack z_inflateBack
# define inflateBackEnd z_inflateBackEnd
# define inflateBackInit z_inflateBackInit
# define inflateBackInit_ z_inflateBackInit_
# define inflateCodesUsed z_inflateCodesUsed
# define inflateCopy z_inflateCopy
# define inflateEnd z_inflateEnd
# define inflateGetDictionary z_inflateGetDictionary
# define inflateGetHeader z_inflateGetHeader
# define inflateInit z_inflateInit
# define inflateInit2 z_inflateInit2
# define inflateInit2_ z_inflateInit2_
# define inflateInit_ z_inflateInit_
# define inflateMark z_inflateMark
# define inflatePrime z_inflatePrime
# define inflateReset z_inflateReset
# define inflateReset2 z_inflateReset2
# define inflateResetKeep z_inflateResetKeep
# define inflateSetDictionary z_inflateSetDictionary
# define inflateSync z_inflateSync
# define inflateSyncPoint z_inflateSyncPoint
# define inflateUndermine z_inflateUndermine
# define inflateValidate z_inflateValidate
# define inflate_copyright z_inflate_copyright
# define inflate_fast z_inflate_fast
# define inflate_table z_inflate_table
# ifndef Z_SOLO
# define uncompress z_uncompress
# define uncompress2 z_uncompress2
# endif
# define zError z_zError
# ifndef Z_SOLO
# define zcalloc z_zcalloc
# define zcfree z_zcfree
# endif
# define zlibCompileFlags z_zlibCompileFlags
# define zlibVersion z_zlibVersion
/* all zlib typedefs in zlib.h and zconf.h */
# define Byte z_Byte
# define Bytef z_Bytef
# define alloc_func z_alloc_func
# define charf z_charf
# define free_func z_free_func
# ifndef Z_SOLO
# define gzFile z_gzFile
# endif
# define gz_header z_gz_header
# define gz_headerp z_gz_headerp
# define in_func z_in_func
# define intf z_intf
# define out_func z_out_func
# define uInt z_uInt
# define uIntf z_uIntf
# define uLong z_uLong
# define uLongf z_uLongf
# define voidp z_voidp
# define voidpc z_voidpc
# define voidpf z_voidpf
/* all zlib structs in zlib.h and zconf.h */
# define gz_header_s z_gz_header_s
# define internal_state z_internal_state
#endif
#if defined(__MSDOS__) && !defined(MSDOS)
# define MSDOS
#endif
#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
# define OS2
#endif
#if defined(_WINDOWS) && !defined(WINDOWS)
# define WINDOWS
#endif
#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
# ifndef WIN32
# define WIN32
# endif
#endif
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
# ifndef SYS16BIT
# define SYS16BIT
# endif
# endif
#endif
/*
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
* than 64k bytes at a time (needed on systems with 16-bit int).
*/
#ifdef SYS16BIT
# define MAXSEG_64K
#endif
#ifdef MSDOS
# define UNALIGNED_OK
#endif
#ifdef __STDC_VERSION__
# ifndef STDC
# define STDC
# endif
# if __STDC_VERSION__ >= 199901L
# ifndef STDC99
# define STDC99
# endif
# endif
#endif
#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
# define STDC
#endif
#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
# define STDC
#endif
#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
# define STDC
#endif
#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
# define STDC
#endif
#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
# define STDC
#endif
#ifndef STDC
# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
# define const /* note: need a more gentle solution here */
# endif
#endif
#if defined(ZLIB_CONST) && !defined(z_const)
# define z_const const
#else
# define z_const
#endif
#ifdef Z_SOLO
# ifdef _WIN64
typedef unsigned long long z_size_t;
# else
typedef unsigned long z_size_t;
# endif
#else
# define z_longlong long long
# if defined(NO_SIZE_T)
typedef unsigned NO_SIZE_T z_size_t;
# elif defined(STDC)
# include <stddef.h>
typedef size_t z_size_t;
# else
typedef unsigned long z_size_t;
# endif
# undef z_longlong
#endif
/* Maximum value for memLevel in deflateInit2 */
#ifndef MAX_MEM_LEVEL
# ifdef MAXSEG_64K
# define MAX_MEM_LEVEL 8
# else
# define MAX_MEM_LEVEL 9
# endif
#endif
/* Maximum value for windowBits in deflateInit2 and inflateInit2.
* WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
* created by gzip. (Files created by minigzip can still be extracted by
* gzip.)
*/
#ifndef MAX_WBITS
# define MAX_WBITS 15 /* 32K LZ77 window */
#endif
/* The memory requirements for deflate are (in bytes):
(1 << (windowBits+2)) + (1 << (memLevel+9))
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
plus a few kilobytes for small objects. For example, if you want to reduce
the default memory requirements from 256K to 128K, compile with
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
Of course this will generally degrade compression (there's no free lunch).
The memory requirements for inflate are (in bytes) 1 << windowBits
that is, 32K for windowBits=15 (default value) plus about 7 kilobytes
for small objects.
*/
/* Type declarations */
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
* just define FAR to be empty.
*/
#ifdef SYS16BIT
# if defined(M_I86SM) || defined(M_I86MM)
/* MSC small or medium model */
# define SMALL_MEDIUM
# ifdef _MSC_VER
# define FAR _far
# else
# define FAR far
# endif
# endif
# if (defined(__SMALL__) || defined(__MEDIUM__))
/* Turbo C small or medium model */
# define SMALL_MEDIUM
# ifdef __BORLANDC__
# define FAR _far
# else
# define FAR far
# endif
# endif
#endif
#if defined(WINDOWS) || defined(WIN32)
/* If building or using zlib as a DLL, define ZLIB_DLL.
* This is not mandatory, but it offers a little performance increase.
*/
# ifdef ZLIB_DLL
# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
# ifdef ZLIB_INTERNAL
# define ZEXTERN extern __declspec(dllexport)
# else
# define ZEXTERN extern __declspec(dllimport)
# endif
# endif
# endif /* ZLIB_DLL */
/* If building or using zlib with the WINAPI/WINAPIV calling convention,
* define ZLIB_WINAPI.
* Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
*/
# ifdef ZLIB_WINAPI
# ifdef FAR
# undef FAR
# endif
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
/* No need for _export, use ZLIB.DEF instead. */
/* For complete Windows compatibility, use WINAPI, not __stdcall. */
# define ZEXPORT WINAPI
# ifdef WIN32
# define ZEXPORTVA WINAPIV
# else
# define ZEXPORTVA FAR CDECL
# endif
# endif
#endif
#if defined (__BEOS__)
# ifdef ZLIB_DLL
# ifdef ZLIB_INTERNAL
# define ZEXPORT __declspec(dllexport)
# define ZEXPORTVA __declspec(dllexport)
# else
# define ZEXPORT __declspec(dllimport)
# define ZEXPORTVA __declspec(dllimport)
# endif
# endif
#endif
#ifndef ZEXTERN
# define ZEXTERN extern
#endif
#ifndef ZEXPORT
# define ZEXPORT
#endif
#ifndef ZEXPORTVA
# define ZEXPORTVA
#endif
#ifndef FAR
# define FAR
#endif
#if !defined(__MACTYPES__)
typedef unsigned char Byte; /* 8 bits */
#endif
typedef unsigned int uInt; /* 16 bits or more */
typedef unsigned long uLong; /* 32 bits or more */
#ifdef SMALL_MEDIUM
/* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
# define Bytef Byte FAR
#else
typedef Byte FAR Bytef;
#endif
typedef char FAR charf;
typedef int FAR intf;
typedef uInt FAR uIntf;
typedef uLong FAR uLongf;
#ifdef STDC
typedef void const *voidpc;
typedef void FAR *voidpf;
typedef void *voidp;
#else
typedef Byte const *voidpc;
typedef Byte FAR *voidpf;
typedef Byte *voidp;
#endif
#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
# include <limits.h>
# if (UINT_MAX == 0xffffffffUL)
# define Z_U4 unsigned
# elif (ULONG_MAX == 0xffffffffUL)
# define Z_U4 unsigned long
# elif (USHRT_MAX == 0xffffffffUL)
# define Z_U4 unsigned short
# endif
#endif
#ifdef Z_U4
typedef Z_U4 z_crc_t;
#else
typedef unsigned long z_crc_t;
#endif
#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
# define Z_HAVE_UNISTD_H
#endif
#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */
# define Z_HAVE_STDARG_H
#endif
#ifdef STDC
# ifndef Z_SOLO
# include <sys/types.h> /* for off_t */
# endif
#endif
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
# ifndef Z_SOLO
# include <stdarg.h> /* for va_list */
# endif
#endif
#ifdef _WIN32
# ifndef Z_SOLO
# include <stddef.h> /* for wchar_t */
# endif
#endif
/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
* "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
* though the former does not conform to the LFS document), but considering
* both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
* equivalently requesting no 64-bit operations
*/
#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
# undef _LARGEFILE64_SOURCE
#endif
#ifndef Z_HAVE_UNISTD_H
# ifdef __WATCOMC__
# define Z_HAVE_UNISTD_H
# endif
#endif
#ifndef Z_HAVE_UNISTD_H
# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)
# define Z_HAVE_UNISTD_H
# endif
#endif
#ifndef Z_SOLO
# if defined(Z_HAVE_UNISTD_H)
# include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
# ifdef VMS
# include <unixio.h> /* for off_t */
# endif
# ifndef z_off_t
# define z_off_t off_t
# endif
# endif
#endif
#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
# define Z_LFS64
#endif
#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
# define Z_LARGE64
#endif
#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
# define Z_WANT64
#endif
#if !defined(SEEK_SET) && !defined(Z_SOLO)
# define SEEK_SET 0 /* Seek from beginning of file. */
# define SEEK_CUR 1 /* Seek from current position. */
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
#endif
#ifndef z_off_t
# define z_off_t long
#endif
#if !defined(_WIN32) && defined(Z_LARGE64)
# define z_off64_t off64_t
#else
# if defined(_WIN32) && !defined(__GNUC__)
# define z_off64_t __int64
# else
# define z_off64_t z_off_t
# endif
#endif
/* MVS linker does not support external names larger than 8 bytes */
#if defined(__MVS__)
#pragma map(deflateInit_,"DEIN")
#pragma map(deflateInit2_,"DEIN2")
#pragma map(deflateEnd,"DEEND")
#pragma map(deflateBound,"DEBND")
#pragma map(inflateInit_,"ININ")
#pragma map(inflateInit2_,"ININ2")
#pragma map(inflateEnd,"INEND")
#pragma map(inflateSync,"INSY")
#pragma map(inflateSetDictionary,"INSEDI")
#pragma map(compressBound,"CMBND")
#pragma map(inflate_table,"INTABL")
#pragma map(inflate_fast,"INFA")
#pragma map(inflate_copyright,"INCOPY")
#endif
#endif /* ZCONF_H */

View file

@ -0,0 +1,13 @@
prefix=/usr/local
exec_prefix=/usr/local
libdir=/usr/local/lib
sharedlibdir=/usr/local/lib
includedir=/usr/local/include
Name: zlib
Description: zlib compression library
Version: 1.3.1
Requires:
Libs: -L${libdir} -L${sharedlibdir} -lz
Cflags: -I${includedir}

153
vendor/mariadb/build/include/config.h vendored Normal file
View file

@ -0,0 +1,153 @@
/*
* Include file constants (processed in LibmysqlIncludeFiles.txt 1
*/
/* #undef HAVE_OPENSSL_APPLINK_C */
#define HAVE_evp_pkey 1
#define HAVE_ALLOCA_H 1
/* #undef HAVE_BIGENDIAN */
#define HAVE_SETLOCALE 1
#define HAVE_NL_LANGINFO 1
#define HAVE_DLFCN_H 1
#define HAVE_FCNTL_H 1
#define HAVE_FLOAT_H 1
#define HAVE_LIMITS_H 1
#define HAVE_LINUX_LIMITS_H 1
#define HAVE_PWD_H 1
/* #undef HAVE_SELECT_H */
#define HAVE_STDDEF_H 1
#define HAVE_STDINT_H 1
#define HAVE_STDLIB_H 1
#define HAVE_STRING_H 1
#define HAVE_SYS_IOCTL_H 1
#define HAVE_SYS_SELECT_H 1
#define HAVE_SYS_SOCKET_H 1
/* #undef HAVE_SYS_STREAM_H */
#define HAVE_SYS_STAT_H 1
/* #undef HAVE_SYS_SYSCTL_H */
#define HAVE_SYS_TYPES_H 1
#define HAVE_SYS_UN_H 1
#define HAVE_UNISTD_H 1
#define HAVE_UCONTEXT_H 1
/* #undef HAVE_BOOST_CONTEXT_H */
/*
* function definitions - processed in LibmysqlFunctions.txt
*/
#define HAVE_DLERROR 1
#define HAVE_DLOPEN 1
#define HAVE_GETPWUID 1
#define HAVE_MEMCPY 1
#define HAVE_POLL 1
/* #undef HAVE_STRTOK_R */
/* #undef HAVE_STRTOL */
/* #undef HAVE_STRTOLL */
/* #undef HAVE_STRTOUL */
/* #undef HAVE_STRTOULL */
/* #undef HAVE_TELL */
/* #undef HAVE_THR_SETCONCURRENCY */
/* #undef HAVE_THR_YIELD */
/* #undef HAVE_VASPRINTF */
/* #undef HAVE_VSNPRINTF */
#define HAVE_CUSERID 1
/*
* types and sizes
*/
#define SIZEOF_CHARP 8
#if defined(SIZEOF_CHARP)
# define HAVE_CHARP 1
#endif
#define SIZEOF_INT 4
#if defined(SIZEOF_INT)
# define HAVE_INT 1
#endif
#define SIZEOF_LONG 8
#if defined(SIZEOF_LONG)
# define HAVE_LONG 1
#endif
#define SIZEOF_LONG_LONG 8
#if defined(SIZEOF_LONG_LONG)
# define HAVE_LONG_LONG 1
#endif
#define SIZEOF_SIZE_T 8
#if defined(SIZEOF_SIZE_T)
# define HAVE_SIZE_T 1
#endif
#define SIZEOF_UINT 4
#if defined(SIZEOF_UINT)
# define HAVE_UINT 1
#endif
#define SIZEOF_USHORT 2
#if defined(SIZEOF_USHORT)
# define HAVE_USHORT 1
#endif
#define SIZEOF_ULONG 8
#if defined(SIZEOF_ULONG)
# define HAVE_ULONG 1
#endif
/* #undef SIZEOF_INT8 */
#if defined(SIZEOF_INT8)
# define HAVE_INT8 1
#endif
/* #undef SIZEOF_UINT8 */
#if defined(SIZEOF_UINT8)
# define HAVE_UINT8 1
#endif
/* #undef SIZEOF_INT16 */
#if defined(SIZEOF_INT16)
# define HAVE_INT16 1
#endif
/* #undef SIZEOF_UINT16 */
#if defined(SIZEOF_UINT16)
# define HAVE_UINT16 1
#endif
/* #undef SIZEOF_INT32 */
#if defined(SIZEOF_INT32)
# define HAVE_INT32 1
#endif
/* #undef SIZEOF_UINT32 */
#if defined(SIZEOF_UINT32)
# define HAVE_UINT32 1
#endif
/* #undef SIZEOF_INT64 */
#if defined(SIZEOF_INT64)
# define HAVE_INT64 1
#endif
/* #undef SIZEOF_UINT64 */
#if defined(SIZEOF_UINT64)
# define HAVE_UINT64 1
#endif
/* #undef SIZEOF_SOCKLEN_T */
#if defined(SIZEOF_SOCKLEN_T)
# define HAVE_SOCKLEN_T 1
#endif
#define SOCKET_SIZE_TYPE socklen_t
#define LOCAL_INFILE_MODE_OFF 0
#define LOCAL_INFILE_MODE_ON 1
#define LOCAL_INFILE_MODE_AUTO 2
#define ENABLED_LOCAL_INFILE LOCAL_INFILE_MODE_AUTO
#define MARIADB_DEFAULT_CHARSET "utf8mb4"
#define DEFAULT_SSL_VERIFY_SERVER_CERT 1

153
vendor/mariadb/build/include/ma_config.h vendored Normal file
View file

@ -0,0 +1,153 @@
/*
* Include file constants (processed in LibmysqlIncludeFiles.txt 1
*/
/* #undef HAVE_OPENSSL_APPLINK_C */
#define HAVE_evp_pkey 1
#define HAVE_ALLOCA_H 1
/* #undef HAVE_BIGENDIAN */
#define HAVE_SETLOCALE 1
#define HAVE_NL_LANGINFO 1
#define HAVE_DLFCN_H 1
#define HAVE_FCNTL_H 1
#define HAVE_FLOAT_H 1
#define HAVE_LIMITS_H 1
#define HAVE_LINUX_LIMITS_H 1
#define HAVE_PWD_H 1
/* #undef HAVE_SELECT_H */
#define HAVE_STDDEF_H 1
#define HAVE_STDINT_H 1
#define HAVE_STDLIB_H 1
#define HAVE_STRING_H 1
#define HAVE_SYS_IOCTL_H 1
#define HAVE_SYS_SELECT_H 1
#define HAVE_SYS_SOCKET_H 1
/* #undef HAVE_SYS_STREAM_H */
#define HAVE_SYS_STAT_H 1
/* #undef HAVE_SYS_SYSCTL_H */
#define HAVE_SYS_TYPES_H 1
#define HAVE_SYS_UN_H 1
#define HAVE_UNISTD_H 1
#define HAVE_UCONTEXT_H 1
/* #undef HAVE_BOOST_CONTEXT_H */
/*
* function definitions - processed in LibmysqlFunctions.txt
*/
#define HAVE_DLERROR 1
#define HAVE_DLOPEN 1
#define HAVE_GETPWUID 1
#define HAVE_MEMCPY 1
#define HAVE_POLL 1
/* #undef HAVE_STRTOK_R */
/* #undef HAVE_STRTOL */
/* #undef HAVE_STRTOLL */
/* #undef HAVE_STRTOUL */
/* #undef HAVE_STRTOULL */
/* #undef HAVE_TELL */
/* #undef HAVE_THR_SETCONCURRENCY */
/* #undef HAVE_THR_YIELD */
/* #undef HAVE_VASPRINTF */
/* #undef HAVE_VSNPRINTF */
#define HAVE_CUSERID 1
/*
* types and sizes
*/
#define SIZEOF_CHARP 8
#if defined(SIZEOF_CHARP)
# define HAVE_CHARP 1
#endif
#define SIZEOF_INT 4
#if defined(SIZEOF_INT)
# define HAVE_INT 1
#endif
#define SIZEOF_LONG 8
#if defined(SIZEOF_LONG)
# define HAVE_LONG 1
#endif
#define SIZEOF_LONG_LONG 8
#if defined(SIZEOF_LONG_LONG)
# define HAVE_LONG_LONG 1
#endif
#define SIZEOF_SIZE_T 8
#if defined(SIZEOF_SIZE_T)
# define HAVE_SIZE_T 1
#endif
#define SIZEOF_UINT 4
#if defined(SIZEOF_UINT)
# define HAVE_UINT 1
#endif
#define SIZEOF_USHORT 2
#if defined(SIZEOF_USHORT)
# define HAVE_USHORT 1
#endif
#define SIZEOF_ULONG 8
#if defined(SIZEOF_ULONG)
# define HAVE_ULONG 1
#endif
/* #undef SIZEOF_INT8 */
#if defined(SIZEOF_INT8)
# define HAVE_INT8 1
#endif
/* #undef SIZEOF_UINT8 */
#if defined(SIZEOF_UINT8)
# define HAVE_UINT8 1
#endif
/* #undef SIZEOF_INT16 */
#if defined(SIZEOF_INT16)
# define HAVE_INT16 1
#endif
/* #undef SIZEOF_UINT16 */
#if defined(SIZEOF_UINT16)
# define HAVE_UINT16 1
#endif
/* #undef SIZEOF_INT32 */
#if defined(SIZEOF_INT32)
# define HAVE_INT32 1
#endif
/* #undef SIZEOF_UINT32 */
#if defined(SIZEOF_UINT32)
# define HAVE_UINT32 1
#endif
/* #undef SIZEOF_INT64 */
#if defined(SIZEOF_INT64)
# define HAVE_INT64 1
#endif
/* #undef SIZEOF_UINT64 */
#if defined(SIZEOF_UINT64)
# define HAVE_UINT64 1
#endif
/* #undef SIZEOF_SOCKLEN_T */
#if defined(SIZEOF_SOCKLEN_T)
# define HAVE_SOCKLEN_T 1
#endif
#define SOCKET_SIZE_TYPE socklen_t
#define LOCAL_INFILE_MODE_OFF 0
#define LOCAL_INFILE_MODE_ON 1
#define LOCAL_INFILE_MODE_AUTO 2
#define ENABLED_LOCAL_INFILE LOCAL_INFILE_MODE_AUTO
#define MARIADB_DEFAULT_CHARSET "utf8mb4"
#define DEFAULT_SSL_VERIFY_SERVER_CERT 1

View file

@ -0,0 +1,44 @@
/* Copyright Abandoned 1996, 1999, 2001 MySQL AB
This file is public domain and comes with NO WARRANTY of any kind */
/* Version numbers for protocol & mysqld */
#ifndef _mariadb_version_h_
#define _mariadb_version_h_
#ifdef _CUSTOMCONFIG_
#include <custom_conf.h>
#else
#define PROTOCOL_VERSION 10
#define MARIADB_CLIENT_VERSION_STR "10.8.8"
#define MARIADB_BASE_VERSION "mariadb-10.8"
#define MARIADB_VERSION_ID 100808
#define MARIADB_PORT 3306
#define MARIADB_UNIX_ADDR "/tmp/mysql.sock"
#ifndef MYSQL_UNIX_ADDR
#define MYSQL_UNIX_ADDR MARIADB_UNIX_ADDR
#endif
#ifndef MYSQL_PORT
#define MYSQL_PORT MARIADB_PORT
#endif
#define MYSQL_CONFIG_NAME "my"
#define MYSQL_VERSION_ID 100808
#define MYSQL_SERVER_VERSION "10.8.8-MariaDB"
#define MARIADB_PACKAGE_VERSION "3.4.10"
#define MARIADB_PACKAGE_VERSION_ID 30410
#define MARIADB_SYSTEM_TYPE "Linux"
#define MARIADB_MACHINE_TYPE "x86_64"
#define MARIADB_PLUGINDIR "/usr/local/lib/mariadb/plugin"
/* mysqld compile time options */
#ifndef MYSQL_CHARSET
#define MYSQL_CHARSET ""
#endif
#endif
/* Source information */
#define CC_SOURCE_REVISION ""
#endif /* _mariadb_version_h_ */

View file

@ -0,0 +1,522 @@
/* Copyright (C) 2010 - 2012 Sergei Golubchik and Monty Program Ab
2015-2016 MariaDB Corporation AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not see <http://www.gnu.org/licenses>
or write to the Free Software Foundation, Inc.,
51 Franklin St., Fifth Floor, Boston, MA 02110, USA */
/**
@file
Support code for the client side (libmariadb) plugins
Client plugins are somewhat different from server plugins, they are simpler.
They do not need to be installed or in any way explicitly loaded on the
client, they are loaded automatically on demand.
One client plugin per shared object, soname *must* match the plugin name.
There is no reference counting and no unloading either.
*/
/* Silence warnings about variable 'unused' being used. */
#define FORCE_INIT_OF_VARS 1
#include <ma_global.h>
#include <ma_sys.h>
#include <ma_common.h>
#include <ma_string.h>
#include <ma_pthread.h>
#include "errmsg.h"
#include <mysql/client_plugin.h>
#ifndef WIN32
#include <dlfcn.h>
#endif
const char *disabled_plugins= "mysql_old_password";
struct st_client_plugin_int {
struct st_client_plugin_int *next;
void *dlhandle;
struct st_mysql_client_plugin *plugin;
};
static my_bool initialized= 0;
static MA_MEM_ROOT mem_root;
static uint valid_plugins[][2]= {
{MYSQL_CLIENT_AUTHENTICATION_PLUGIN, MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION},
{MARIADB_CLIENT_PVIO_PLUGIN, MARIADB_CLIENT_PVIO_PLUGIN_INTERFACE_VERSION},
{MARIADB_CLIENT_TRACE_PLUGIN, MARIADB_CLIENT_TRACE_PLUGIN_INTERFACE_VERSION},
{MARIADB_CLIENT_REMOTEIO_PLUGIN, MARIADB_CLIENT_REMOTEIO_PLUGIN_INTERFACE_VERSION},
{MARIADB_CLIENT_CONNECTION_PLUGIN, MARIADB_CLIENT_CONNECTION_PLUGIN_INTERFACE_VERSION},
{MARIADB_CLIENT_COMPRESSION_PLUGIN, MARIADB_CLIENT_COMPRESSION_PLUGIN_INTERFACE_VERSION},
{0, 0}
};
/*
Loaded plugins are stored in a linked list.
The list is append-only, the elements are added to the head (like in a stack).
The elements are added under a mutex, but the list can be read and traversed
without any mutex because once an element is added to the list, it stays
there. The main purpose of a mutex is to prevent two threads from
loading the same plugin twice in parallel.
*/
struct st_client_plugin_int *plugin_list[MYSQL_CLIENT_MAX_PLUGINS + MARIADB_CLIENT_MAX_PLUGINS];
#ifdef THREAD
static pthread_mutex_t LOCK_load_client_plugin;
#endif
extern struct st_mysql_client_plugin_AUTH mysql_native_password_client_plugin;
extern struct st_mysql_client_plugin_AUTH mysql_old_password_client_plugin;
extern struct st_mysql_client_plugin_COMPRESSION zlib_client_plugin;
extern struct st_mysql_client_plugin_PVIO pvio_socket_client_plugin;
struct st_mysql_client_plugin *mysql_client_builtins[]=
{
(struct st_mysql_client_plugin *)&mysql_native_password_client_plugin,
(struct st_mysql_client_plugin *)&mysql_old_password_client_plugin,
(struct st_mysql_client_plugin *)&zlib_client_plugin,
(struct st_mysql_client_plugin *)&pvio_socket_client_plugin,
0
};
static int is_not_initialized(MYSQL *mysql, const char *name)
{
if (initialized)
return 0;
my_set_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD,
SQLSTATE_UNKNOWN, ER(CR_AUTH_PLUGIN_CANNOT_LOAD),
name, "not initialized");
return 1;
}
static int get_plugin_nr(uint type)
{
uint i= 0;
for(; valid_plugins[i][1]; i++)
if (valid_plugins[i][0] == type)
return i;
return -1;
}
static const char *check_plugin_version(struct st_mysql_client_plugin *plugin, unsigned int version)
{
if (plugin->interface_version >> 8 != version >> 8)
return "Incompatible client plugin interface";
return 0;
}
/**
finds a plugin in the list
@param name plugin name to search for
@param type plugin type
@note this does NOT necessarily need a mutex, take care!
@retval a pointer to a found plugin or 0
*/
static struct st_mysql_client_plugin *find_plugin(const char *name, int type)
{
struct st_client_plugin_int *p;
int plugin_nr= get_plugin_nr(type);
DBUG_ASSERT(initialized);
if (plugin_nr == -1)
return 0;
if (!name)
{
if (plugin_list[plugin_nr])
return plugin_list[plugin_nr]->plugin;
return NULL;
}
for (p= plugin_list[plugin_nr]; p; p= p->next)
{
if (strcmp(p->plugin->name, name) == 0)
return p->plugin;
}
return NULL;
}
/**
verifies the plugin and adds it to the list
@param mysql MYSQL structure (for error reporting)
@param plugin plugin to install
@param dlhandle a handle to the shared object (returned by dlopen)
or 0 if the plugin was not dynamically loaded
@param argc number of arguments in the 'va_list args'
@param args arguments passed to the plugin initialization function
@retval a pointer to an installed plugin or 0
*/
static struct st_mysql_client_plugin *
add_plugin(MYSQL *mysql, struct st_mysql_client_plugin *plugin, void *dlhandle,
int argc, va_list args)
{
const char *errmsg;
struct st_client_plugin_int plugin_int, *p;
char errbuf[1024];
int plugin_nr;
DBUG_ASSERT(initialized);
plugin_int.plugin= plugin;
plugin_int.dlhandle= dlhandle;
if ((plugin_nr= get_plugin_nr(plugin->type)) == -1)
{
errmsg= "Unknown client plugin type";
goto err1;
}
if ((errmsg= check_plugin_version(plugin, valid_plugins[plugin_nr][1])))
goto err1;
/* Call the plugin initialization function, if any */
if (plugin->init && plugin->init(errbuf, sizeof(errbuf), argc, args))
{
errmsg= errbuf;
goto err1;
}
p= (struct st_client_plugin_int *)
ma_memdup_root(&mem_root, (char *)&plugin_int, sizeof(plugin_int));
if (!p)
{
errmsg= "Out of memory";
goto err2;
}
p->next= plugin_list[plugin_nr];
plugin_list[plugin_nr]= p;
return plugin;
err2:
if (plugin->deinit)
plugin->deinit();
err1:
my_set_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, SQLSTATE_UNKNOWN,
ER(CR_AUTH_PLUGIN_CANNOT_LOAD), plugin->name, errmsg);
if (dlhandle)
(void)dlclose(dlhandle);
return NULL;
}
/**
Loads plugins which are specified in the environment variable
LIBMYSQL_PLUGINS.
Multiple plugins must be separated by semicolon. This function doesn't
return or log an error.
The function is be called by mysql_client_plugin_init
@todo
Support extended syntax, passing parameters to plugins, for example
LIBMYSQL_PLUGINS="plugin1(param1,param2);plugin2;..."
or
LIBMYSQL_PLUGINS="plugin1=int:param1,str:param2;plugin2;..."
*/
static void load_env_plugins(MYSQL *mysql)
{
char *plugs, *free_env, *s= getenv("LIBMYSQL_PLUGINS");
if (ma_check_env_str(s))
return;
free_env= strdup(s);
plugs= s= free_env;
if (!free_env)
{
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
return;
}
do {
if ((s= strchr(plugs, ';')))
*s= '\0';
mysql_load_plugin(mysql, plugs, -1, 0);
plugs= s + 1;
} while (s);
free(free_env);
}
/********** extern functions to be used by libmariadb *********************/
/**
Initializes the client plugin layer.
This function must be called before any other client plugin function.
@retval 0 successful
@retval != 0 error occurred
*/
int mysql_client_plugin_init()
{
MYSQL mysql;
struct st_mysql_client_plugin **builtin;
va_list unused;
LINT_INIT_STRUCT(unused);
if (initialized)
return 0;
memset(&mysql, 0, sizeof(mysql)); /* dummy mysql for set_mysql_extended_error */
pthread_mutex_init(&LOCK_load_client_plugin, NULL);
ma_init_alloc_root(&mem_root, 128, 128);
memset(&plugin_list, 0, sizeof(plugin_list));
initialized= 1;
pthread_mutex_lock(&LOCK_load_client_plugin);
for (builtin= mysql_client_builtins; *builtin; builtin++)
add_plugin(&mysql, *builtin, 0, 0, unused);
pthread_mutex_unlock(&LOCK_load_client_plugin);
load_env_plugins(&mysql);
return 0;
}
/**
Deinitializes the client plugin layer.
Unloads all client plugins and frees any associated resources.
*/
void mysql_client_plugin_deinit()
{
int i;
struct st_client_plugin_int *p;
if (!initialized)
return;
for (i=0; i < MYSQL_CLIENT_MAX_PLUGINS; i++)
for (p= plugin_list[i]; p; p= p->next)
{
if (p->plugin->deinit)
p->plugin->deinit();
if (p->dlhandle)
(void)dlclose(p->dlhandle);
}
memset(&plugin_list, 0, sizeof(plugin_list));
initialized= 0;
ma_free_root(&mem_root, MYF(0));
pthread_mutex_destroy(&LOCK_load_client_plugin);
}
/************* public facing functions, for client consumption *********/
/* see <mysql/client_plugin.h> for a full description */
struct st_mysql_client_plugin * STDCALL
mysql_client_register_plugin(MYSQL *mysql,
struct st_mysql_client_plugin *plugin)
{
struct st_mysql_client_plugin *found_plugin= NULL;
va_list unused;
LINT_INIT_STRUCT(unused);
if (is_not_initialized(mysql, plugin->name))
return NULL;
pthread_mutex_lock(&LOCK_load_client_plugin);
/* make sure the plugin wasn't loaded meanwhile */
if (!(found_plugin= find_plugin(plugin->name, plugin->type)))
found_plugin= add_plugin(mysql, plugin, 0, 0, unused);
pthread_mutex_unlock(&LOCK_load_client_plugin);
return found_plugin;
}
/* see <mysql/client_plugin.h> for a full description */
struct st_mysql_client_plugin * STDCALL
mysql_load_plugin_v(MYSQL *mysql, const char *name, int type,
int argc, va_list args)
{
const char *errmsg;
#ifdef _WIN32
char errbuf[1024];
#endif
char dlpath[FN_REFLEN+1];
void *sym, *dlhandle = NULL;
struct st_mysql_client_plugin *plugin;
char *env_plugin_dir= getenv("MARIADB_PLUGIN_DIR");
CLEAR_CLIENT_ERROR(mysql);
if (is_not_initialized(mysql, name))
return NULL;
pthread_mutex_lock(&LOCK_load_client_plugin);
/* make sure the plugin wasn't loaded meanwhile */
if (type >= 0 && find_plugin(name, type))
{
errmsg= "it is already loaded";
goto err;
}
/* Compile dll path */
#ifndef WIN32
snprintf(dlpath, sizeof(dlpath) - 1, "%s/%s%s",
mysql->options.extension && mysql->options.extension->plugin_dir ?
mysql->options.extension->plugin_dir : (env_plugin_dir) ? env_plugin_dir :
MARIADB_PLUGINDIR, name, SO_EXT);
#else
{
char *p= (mysql->options.extension && mysql->options.extension->plugin_dir) ?
mysql->options.extension->plugin_dir : env_plugin_dir;
snprintf(dlpath, sizeof(dlpath), "%s%s%s%s", p ? p : "", p ? "\\" : "", name, SO_EXT);
}
#endif
if (strpbrk(name, "()[]!@#$%^&/*;.,'?\\"))
{
errmsg= "invalid plugin name";
goto err;
}
/* Open new dll handle */
if (!(dlhandle= dlopen((const char *)dlpath, RTLD_NOW)))
{
#ifdef _WIN32
char winmsg[255];
size_t len;
winmsg[0] = 0;
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
winmsg, 255, NULL);
len= strlen(winmsg);
while (len > 0 && (winmsg[len - 1] == '\n' || winmsg[len - 1] == '\r'))
len--;
if (len)
winmsg[len] = 0;
snprintf(errbuf, sizeof(errbuf), "%s Library path is '%s'", winmsg, dlpath);
errmsg= errbuf;
#else
errmsg= dlerror();
#endif
goto err;
}
if (!(sym= dlsym(dlhandle, plugin_declarations_sym)))
{
errmsg= "not a plugin";
(void)dlclose(dlhandle);
goto err;
}
plugin= (struct st_mysql_client_plugin*)sym;
if (type >=0 && type != plugin->type)
{
errmsg= "type mismatch";
goto err;
}
if (strcmp(name, plugin->name))
{
errmsg= "name mismatch";
goto err;
}
if (type < 0 && find_plugin(name, plugin->type))
{
errmsg= "it is already loaded";
goto err;
}
plugin= add_plugin(mysql, plugin, dlhandle, argc, args);
pthread_mutex_unlock(&LOCK_load_client_plugin);
return plugin;
err:
if (dlhandle)
dlclose(dlhandle);
pthread_mutex_unlock(&LOCK_load_client_plugin);
my_set_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, SQLSTATE_UNKNOWN,
ER(CR_AUTH_PLUGIN_CANNOT_LOAD), name, errmsg);
return NULL;
}
/* see <mysql/client_plugin.h> for a full description */
struct st_mysql_client_plugin * STDCALL
mysql_load_plugin(MYSQL *mysql, const char *name, int type, int argc, ...)
{
struct st_mysql_client_plugin *p;
va_list args;
va_start(args, argc);
p= mysql_load_plugin_v(mysql, name, type, argc, args);
va_end(args);
return p;
}
/* see <mysql/client_plugin.h> for a full description */
struct st_mysql_client_plugin * STDCALL
mysql_client_find_plugin(MYSQL *mysql, const char *name, int type)
{
struct st_mysql_client_plugin *p;
int plugin_nr= get_plugin_nr(type);
if (is_not_initialized(mysql, name))
return NULL;
if (plugin_nr == -1)
{
my_set_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, SQLSTATE_UNKNOWN,
ER(CR_AUTH_PLUGIN_CANNOT_LOAD), name, "invalid type");
}
if ((p= find_plugin(name, type)))
return p;
/* not found, load it */
return mysql_load_plugin(mysql, name, type, 0);
}

View file

@ -0,0 +1,379 @@
VERSION {
libmysqlclient_18 {
global:
mysql_affected_rows;
mysql_autocommit;
mysql_change_user;
mysql_character_set_name;
mysql_client_find_plugin;
mysql_client_register_plugin;
mysql_close;
mysql_commit;
mysql_data_seek;
mysql_debug;
mysql_dump_debug_info;
mysql_embedded;
mysql_eof;
mysql_errno;
mysql_error;
mysql_escape_string;
mysql_fetch_field;
mysql_fetch_field_direct;
mysql_fetch_fields;
mysql_fetch_lengths;
mysql_fetch_row;
mysql_field_count;
mysql_field_seek;
mysql_field_tell;
mysql_free_result;
mysql_get_character_set_info;
mysql_get_charset_by_name;
mysql_get_charset_by_nr;
mysql_get_client_info;
mysql_get_client_version;
mysql_get_host_info;
mysql_get_option;
mysql_get_optionv;
mysql_get_parameters;
mysql_get_proto_info;
mysql_get_server_info;
mysql_get_server_name;
mysql_get_server_version;
mysql_get_socket;
mysql_get_ssl_cipher;
mysql_hex_string;
mysql_info;
mysql_init;
mysql_insert_id;
mysql_kill;
mysql_list_dbs;
mysql_list_fields;
mysql_list_processes;
mysql_list_tables;
mysql_load_plugin;
mysql_load_plugin_v;
mysql_more_results;
mysql_net_field_length;
mysql_net_read_packet;
mysql_next_result;
mysql_num_fields;
mysql_num_rows;
mysql_options;
mysql_options4;
mysql_ping;
mysql_query;
mysql_read_query_result;
mysql_real_connect;
mysql_real_escape_string;
mysql_real_query;
mysql_refresh;
mysql_reset_connection;
mysql_rollback;
mysql_row_seek;
mysql_row_tell;
mysql_select_db;
mysql_send_query;
mysql_server_end;
mysql_server_init;
mysql_session_track_get_next;
mysql_session_track_get_first;
mysql_set_character_set;
mysql_set_local_infile_default;
mysql_set_local_infile_handler;
mysql_set_server_option;
mysql_shutdown;
mysql_sqlstate;
mysql_ssl_set;
mysql_stat;
mysql_stmt_affected_rows;
mysql_stmt_attr_get;
mysql_stmt_attr_set;
mysql_stmt_bind_param;
mysql_stmt_bind_result;
mysql_stmt_close;
mysql_stmt_data_seek;
mysql_stmt_errno;
mysql_stmt_error;
mysql_stmt_execute;
mysql_stmt_fetch;
mysql_stmt_fetch_column;
mysql_stmt_field_count;
mysql_stmt_free_result;
mysql_stmt_init;
mysql_stmt_insert_id;
mysql_stmt_more_results;
mysql_stmt_next_result;
mysql_stmt_num_rows;
mysql_stmt_param_count;
mysql_stmt_param_metadata;
mysql_stmt_prepare;
mysql_stmt_reset;
mysql_stmt_result_metadata;
mysql_stmt_row_seek;
mysql_stmt_row_tell;
mysql_stmt_send_long_data;
mysql_stmt_sqlstate;
mysql_stmt_store_result;
mysql_store_result;
mysql_thread_end;
mysql_thread_id;
mysql_thread_init;
mysql_thread_safe;
mysql_use_result;
mysql_warning_count;
local:
*;
};
libmariadbclient_18 {
};
};
"mysql_affected_rows@libmariadbclient_18" = mysql_affected_rows;
"mysql_autocommit@libmariadbclient_18" = mysql_autocommit;
"mysql_change_user@libmariadbclient_18" = mysql_change_user;
"mysql_character_set_name@libmariadbclient_18" = mysql_character_set_name;
"mysql_client_find_plugin@libmariadbclient_18" = mysql_client_find_plugin;
"mysql_client_register_plugin@libmariadbclient_18" = mysql_client_register_plugin;
"mysql_close@libmariadbclient_18" = mysql_close;
"mysql_commit@libmariadbclient_18" = mysql_commit;
"mysql_data_seek@libmariadbclient_18" = mysql_data_seek;
"mysql_debug@libmariadbclient_18" = mysql_debug;
"mysql_dump_debug_info@libmariadbclient_18" = mysql_dump_debug_info;
"mysql_embedded@libmariadbclient_18" = mysql_embedded;
"mysql_eof@libmariadbclient_18" = mysql_eof;
"mysql_errno@libmariadbclient_18" = mysql_errno;
"mysql_error@libmariadbclient_18" = mysql_error;
"mysql_escape_string@libmariadbclient_18" = mysql_escape_string;
"mysql_fetch_field@libmariadbclient_18" = mysql_fetch_field;
"mysql_fetch_field_direct@libmariadbclient_18" = mysql_fetch_field_direct;
"mysql_fetch_fields@libmariadbclient_18" = mysql_fetch_fields;
"mysql_fetch_lengths@libmariadbclient_18" = mysql_fetch_lengths;
"mysql_fetch_row@libmariadbclient_18" = mysql_fetch_row;
"mysql_field_count@libmariadbclient_18" = mysql_field_count;
"mysql_field_seek@libmariadbclient_18" = mysql_field_seek;
"mysql_field_tell@libmariadbclient_18" = mysql_field_tell;
"mysql_free_result@libmariadbclient_18" = mysql_free_result;
"mysql_get_character_set_info@libmariadbclient_18" = mysql_get_character_set_info;
"mysql_get_charset_by_name@libmariadbclient_18" = mysql_get_charset_by_name;
"mysql_get_charset_by_nr@libmariadbclient_18" = mysql_get_charset_by_nr;
"mysql_get_client_info@libmariadbclient_18" = mysql_get_client_info;
"mysql_get_client_version@libmariadbclient_18" = mysql_get_client_version;
"mysql_get_host_info@libmariadbclient_18" = mysql_get_host_info;
"mysql_get_option@libmariadbclient_18" = mysql_get_option;
"mysql_get_optionv@libmariadbclient_18" = mysql_get_optionv;
"mysql_get_parameters@libmariadbclient_18" = mysql_get_parameters;
"mysql_get_proto_info@libmariadbclient_18" = mysql_get_proto_info;
"mysql_get_server_info@libmariadbclient_18" = mysql_get_server_info;
"mysql_get_server_name@libmariadbclient_18" = mysql_get_server_name;
"mysql_get_server_version@libmariadbclient_18" = mysql_get_server_version;
"mysql_get_socket@libmariadbclient_18" = mysql_get_socket;
"mysql_get_ssl_cipher@libmariadbclient_18" = mysql_get_ssl_cipher;
"mysql_hex_string@libmariadbclient_18" = mysql_hex_string;
"mysql_info@libmariadbclient_18" = mysql_info;
"mysql_init@libmariadbclient_18" = mysql_init;
"mysql_insert_id@libmariadbclient_18" = mysql_insert_id;
"mysql_kill@libmariadbclient_18" = mysql_kill;
"mysql_list_dbs@libmariadbclient_18" = mysql_list_dbs;
"mysql_list_fields@libmariadbclient_18" = mysql_list_fields;
"mysql_list_processes@libmariadbclient_18" = mysql_list_processes;
"mysql_list_tables@libmariadbclient_18" = mysql_list_tables;
"mysql_load_plugin@libmariadbclient_18" = mysql_load_plugin;
"mysql_load_plugin_v@libmariadbclient_18" = mysql_load_plugin_v;
"mysql_more_results@libmariadbclient_18" = mysql_more_results;
"mysql_net_field_length@libmariadbclient_18" = mysql_net_field_length;
"mysql_net_read_packet@libmariadbclient_18" = mysql_net_read_packet;
"mysql_next_result@libmariadbclient_18" = mysql_next_result;
"mysql_num_fields@libmariadbclient_18" = mysql_num_fields;
"mysql_num_rows@libmariadbclient_18" = mysql_num_rows;
"mysql_options@libmariadbclient_18" = mysql_options;
"mysql_options4@libmariadbclient_18" = mysql_options4;
"mysql_ping@libmariadbclient_18" = mysql_ping;
"mysql_query@libmariadbclient_18" = mysql_query;
"mysql_read_query_result@libmariadbclient_18" = mysql_read_query_result;
"mysql_real_connect@libmariadbclient_18" = mysql_real_connect;
"mysql_real_escape_string@libmariadbclient_18" = mysql_real_escape_string;
"mysql_real_query@libmariadbclient_18" = mysql_real_query;
"mysql_refresh@libmariadbclient_18" = mysql_refresh;
"mysql_reset_connection@libmariadbclient_18" = mysql_reset_connection;
"mysql_rollback@libmariadbclient_18" = mysql_rollback;
"mysql_row_seek@libmariadbclient_18" = mysql_row_seek;
"mysql_row_tell@libmariadbclient_18" = mysql_row_tell;
"mysql_select_db@libmariadbclient_18" = mysql_select_db;
"mysql_send_query@libmariadbclient_18" = mysql_send_query;
"mysql_server_end@libmariadbclient_18" = mysql_server_end;
"mysql_server_init@libmariadbclient_18" = mysql_server_init;
"mysql_session_track_get_next@libmariadbclient_18" = mysql_session_track_get_next;
"mysql_session_track_get_first@libmariadbclient_18" = mysql_session_track_get_first;
"mysql_set_character_set@libmariadbclient_18" = mysql_set_character_set;
"mysql_set_local_infile_default@libmariadbclient_18" = mysql_set_local_infile_default;
"mysql_set_local_infile_handler@libmariadbclient_18" = mysql_set_local_infile_handler;
"mysql_set_server_option@libmariadbclient_18" = mysql_set_server_option;
"mysql_shutdown@libmariadbclient_18" = mysql_shutdown;
"mysql_sqlstate@libmariadbclient_18" = mysql_sqlstate;
"mysql_ssl_set@libmariadbclient_18" = mysql_ssl_set;
"mysql_stat@libmariadbclient_18" = mysql_stat;
"mysql_stmt_affected_rows@libmariadbclient_18" = mysql_stmt_affected_rows;
"mysql_stmt_attr_get@libmariadbclient_18" = mysql_stmt_attr_get;
"mysql_stmt_attr_set@libmariadbclient_18" = mysql_stmt_attr_set;
"mysql_stmt_bind_param@libmariadbclient_18" = mysql_stmt_bind_param;
"mysql_stmt_bind_result@libmariadbclient_18" = mysql_stmt_bind_result;
"mysql_stmt_close@libmariadbclient_18" = mysql_stmt_close;
"mysql_stmt_data_seek@libmariadbclient_18" = mysql_stmt_data_seek;
"mysql_stmt_errno@libmariadbclient_18" = mysql_stmt_errno;
"mysql_stmt_error@libmariadbclient_18" = mysql_stmt_error;
"mysql_stmt_execute@libmariadbclient_18" = mysql_stmt_execute;
"mysql_stmt_fetch@libmariadbclient_18" = mysql_stmt_fetch;
"mysql_stmt_fetch_column@libmariadbclient_18" = mysql_stmt_fetch_column;
"mysql_stmt_field_count@libmariadbclient_18" = mysql_stmt_field_count;
"mysql_stmt_free_result@libmariadbclient_18" = mysql_stmt_free_result;
"mysql_stmt_init@libmariadbclient_18" = mysql_stmt_init;
"mysql_stmt_insert_id@libmariadbclient_18" = mysql_stmt_insert_id;
"mysql_stmt_more_results@libmariadbclient_18" = mysql_stmt_more_results;
"mysql_stmt_next_result@libmariadbclient_18" = mysql_stmt_next_result;
"mysql_stmt_num_rows@libmariadbclient_18" = mysql_stmt_num_rows;
"mysql_stmt_param_count@libmariadbclient_18" = mysql_stmt_param_count;
"mysql_stmt_param_metadata@libmariadbclient_18" = mysql_stmt_param_metadata;
"mysql_stmt_prepare@libmariadbclient_18" = mysql_stmt_prepare;
"mysql_stmt_reset@libmariadbclient_18" = mysql_stmt_reset;
"mysql_stmt_result_metadata@libmariadbclient_18" = mysql_stmt_result_metadata;
"mysql_stmt_row_seek@libmariadbclient_18" = mysql_stmt_row_seek;
"mysql_stmt_row_tell@libmariadbclient_18" = mysql_stmt_row_tell;
"mysql_stmt_send_long_data@libmariadbclient_18" = mysql_stmt_send_long_data;
"mysql_stmt_sqlstate@libmariadbclient_18" = mysql_stmt_sqlstate;
"mysql_stmt_store_result@libmariadbclient_18" = mysql_stmt_store_result;
"mysql_store_result@libmariadbclient_18" = mysql_store_result;
"mysql_thread_end@libmariadbclient_18" = mysql_thread_end;
"mysql_thread_id@libmariadbclient_18" = mysql_thread_id;
"mysql_thread_init@libmariadbclient_18" = mysql_thread_init;
"mysql_thread_safe@libmariadbclient_18" = mysql_thread_safe;
"mysql_use_result@libmariadbclient_18" = mysql_use_result;
"mysql_warning_count@libmariadbclient_18" = mysql_warning_count;
VERSION {
libmariadb_3 {
global:
mariadb_cancel;
mariadb_connection;
mariadb_convert_string;
ma_pvio_register_callback;
mariadb_get_charset_by_name;
mariadb_stmt_execute_direct;
mariadb_get_charset_by_nr;
mariadb_get_info;
mariadb_get_infov;
mysql_get_timeout_value;
mysql_get_timeout_value_ms;
mysql_optionsv;
mysql_ps_fetch_functions;
mariadb_reconnect;
mysql_stmt_warning_count;
mariadb_stmt_fetch_fields;
mariadb_rpl_open;
mariadb_rpl_close;
mariadb_rpl_fetch;
mariadb_rpl_optionsv;
mariadb_rpl_get_optionsv;
mariadb_rpl_init_ex;
mariadb_free_rpl_event;
mariadb_field_attr;
mariadb_deinitialize_ssl;
mariadb_dyncol_check;
mariadb_dyncol_column_cmp_named;
mariadb_dyncol_column_count;
mariadb_dyncol_create_many_named;
mariadb_dyncol_create_many_num;
mariadb_dyncol_exists_named;
mariadb_dyncol_exists_num;
mariadb_dyncol_free;
mariadb_dyncol_get_named;
mariadb_dyncol_get_num;
mariadb_dyncol_has_names;
mariadb_dyncol_json;
mariadb_dyncol_list_named;
mariadb_dyncol_list_num;
mariadb_dyncol_unpack;
mariadb_dyncol_update_many_named;
mariadb_dyncol_update_many_num;
mariadb_dyncol_val_double;
mariadb_dyncol_val_long;
mariadb_dyncol_val_str;
mysql_autocommit_cont;
mysql_autocommit_start;
mysql_change_user_cont;
mysql_change_user_start;
mysql_close_cont;
mysql_close_start;
mysql_commit_cont;
mysql_commit_start;
mysql_dump_debug_info_cont;
mysql_dump_debug_info_start;
mysql_fetch_row_cont;
mysql_fetch_row_start;
mysql_free_result_cont;
mysql_free_result_start;
mysql_kill_cont;
mysql_kill_start;
mysql_list_fields_cont;
mysql_list_fields_start;
mysql_next_result_cont;
mysql_next_result_start;
mysql_ping_cont;
mysql_ping_start;
mysql_reset_connection_start;
mysql_reset_connection_cont;
mysql_query_cont;
mysql_query_start;
mysql_read_query_result_cont;
mysql_read_query_result_start;
mysql_real_connect_cont;
mysql_real_connect_start;
mysql_real_query_cont;
mysql_real_query_start;
mysql_refresh_cont;
mysql_refresh_start;
mysql_rollback_cont;
mysql_rollback_start;
mysql_select_db_cont;
mysql_select_db_start;
mysql_send_query_cont;
mysql_send_query_start;
mysql_set_character_set_cont;
mysql_set_character_set_start;
mysql_set_server_option_cont;
mysql_set_server_option_start;
mysql_shutdown_cont;
mysql_shutdown_start;
mysql_stat_cont;
mysql_stat_start;
mysql_stmt_close_cont;
mysql_stmt_close_start;
mysql_stmt_execute_cont;
mysql_stmt_execute_start;
mysql_stmt_fetch_cont;
mysql_stmt_fetch_start;
mysql_stmt_free_result_cont;
mysql_stmt_free_result_start;
mysql_stmt_next_result_cont;
mysql_stmt_next_result_start;
mysql_stmt_prepare_cont;
mysql_stmt_prepare_start;
mysql_stmt_reset_cont;
mysql_stmt_reset_start;
mysql_stmt_send_long_data_cont;
mysql_stmt_send_long_data_start;
mysql_stmt_store_result_cont;
mysql_stmt_store_result_start;
mysql_store_result_cont;
mysql_store_result_start;
local:
*;
};
};
VERSION {
libmariadb_3_3_5 {
global:
mariadb_rpl_extract_rows;
mariadb_rpl_error;
mariadb_rpl_errno;
local:
*;
};
};

View file

@ -0,0 +1,20 @@
#
# pkg_config.pc.in
#
# pkg_config configuration file
# For a detailed description of options, please visit
# Dan Nicholson’s Guide to pkg-config (http://www.freedesktop.org/wiki/Software/pkg-config/)
#
prefix=/usr/local
includedir=${prefix}/include/mariadb/
libdir=${prefix}/lib/mariadb/
Name: libmariadb
Version: 3.4.10
Description: MariaDB Connector/C dynamic library
Cflags: -I${includedir}
Libs: -L${libdir} -lmariadb
Libs.private: -ldl -lm -l/home/scott/claude/calog/vendor/openssl/libssl.a -l/home/scott/claude/calog/vendor/openssl/libcrypto.a

View file

@ -0,0 +1,321 @@
#include <ma_config.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <mariadb_version.h>
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if defined(__FreeBSD__) || defined(__DragonFly__)
#include <sys/sysctl.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <unistd.h>
#ifdef HAVE_LINUX_LIMITS_H
#include <linux/limits.h>
#endif
#include <string.h>
#if defined(__APPLE__)
#include <mach-o/dyld.h>
#endif
static char *mariadb_progname;
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
#define INCLUDE "-I%s/include/mariadb -I%s/include/mariadb/mysql"
#define LIBS "-L%s/lib/mariadb/ -lmariadb"
#define LIBS_SYS "-ldl -lm -l/home/scott/claude/calog/vendor/openssl/libssl.a -l/home/scott/claude/calog/vendor/openssl/libcrypto.a"
#define CFLAGS INCLUDE
#define VERSION "10.8.8"
#define CC_VERSION "3.4.10"
#define PLUGIN_DIR "%s/lib/mariadb/plugin"
#define SOCKET "/tmp/mysql.sock"
#define PORT "3306"
#ifdef HAVE_TLS
#define TLS_LIBRARY_VERSION "OpenSSL 3.5.7"
#else
#define TLS_LIBRARY_VERSION ""
#endif
#define PKG_INCLUDEDIR "%s/include/mariadb"
#define PKG_PLUGINDIR "%s/lib/mariadb/plugin"
#define PKG_LIBDIR "%s/lib/mariadb"
#ifdef HAVE_EMBEDDED
#define EMBEDDED_LIBS "-L/usr/local/lib/mariadb/ -lmariadbd -ldl -lm -l/home/scott/claude/calog/vendor/openssl/libssl.a -l/home/scott/claude/calog/vendor/openssl/libcrypto.a"
#endif
#if defined(SOLARIS) || defined(__sun)
#define OPT_STRING_TYPE (char *)
#else
#define OPT_STRING_TYPE
#endif
static struct option long_options[]=
{
{OPT_STRING_TYPE "cflags", no_argument, 0, 'a'},
{OPT_STRING_TYPE "help", no_argument, 0, 'b'},
{OPT_STRING_TYPE "include", no_argument, 0, 'c'},
{OPT_STRING_TYPE "libs", no_argument, 0, 'd'},
{OPT_STRING_TYPE "libs_r", no_argument, 0, 'e'},
{OPT_STRING_TYPE "libs_sys", no_argument, 0, 'l'},
{OPT_STRING_TYPE "version", no_argument, 0, 'f'},
{OPT_STRING_TYPE "cc_version", no_argument, 0, 'g'},
{OPT_STRING_TYPE "socket", no_argument, 0, 'h'},
{OPT_STRING_TYPE "port", no_argument, 0, 'i'},
{OPT_STRING_TYPE "plugindir", no_argument, 0, 'j'},
{OPT_STRING_TYPE "tlsinfo", no_argument, 0, 'k'},
{OPT_STRING_TYPE "variable", 2, 0, 'm'},
#ifdef HAVE_EMBEDDED
{OPT_STRING_TYPE "libmysqld-libs", no_argument, 0, 'n' },
{OPT_STRING_TYPE "embedded-libs", no_argument, 0, 'n' },
{OPT_STRING_TYPE "embedded", no_argument, 0, 'n' },
#endif
{NULL, 0, 0, 0}
};
static struct {
const char *variable;
const char *value;
} variables[] = {
{"pkgincludedir", PKG_INCLUDEDIR},
{"pkglibdir", PKG_LIBDIR},
{"pkgplugindir", PKG_PLUGINDIR},
{NULL, NULL}
};
char installation_dir[PATH_MAX];
static const char *values[]=
{
CFLAGS,
NULL,
INCLUDE,
LIBS,
LIBS,
LIBS_SYS,
VERSION,
CC_VERSION,
SOCKET,
PORT,
PLUGIN_DIR,
TLS_LIBRARY_VERSION,
"VAR VAR is one of:"
#ifdef HAVE_EMBEDDED
,EMBEDDED_LIBS
#endif
};
void usage(void)
{
int i=0;
puts("Copyright 2011-2020 MariaDB Corporation AB");
puts("Get compiler flags for using the MariaDB Connector/C.");
printf("Usage: %s [OPTIONS]\n", mariadb_progname);
printf("Compiler: GNU 13.3.0\n");
while (long_options[i].name)
{
if (!long_options[i].has_arg)
{
if (values[i])
{
printf(" --%-12s [", long_options[i].name);
printf(values[i], installation_dir, installation_dir);
printf("]\n");
}
} else
{
printf(" --%s=%s\n", long_options[i].name, values[i]);
/* Variables */
if (long_options[i].val == 'm')
{
int i= 0;
while (variables[i].variable)
{
printf(" %-14s [", variables[i].variable);
printf(variables[i].value, installation_dir);
printf("]\n");
i++;
}
}
}
i++;
}
}
/*
mariadb_get_install_location()
Tries to find the installation location in the following order:
1) check if MARIADB_CONFIG environment variable was set
2) try to determine the installation directory from executable path
3) Fallback if 1 and 2 failed: use CMAKE_SYSROOT/CMAKE_INSTALL_PREFIX
*/
static void mariadb_get_install_location()
{
char *p= NULL;
struct stat s;
/* Check environment variable MARIADB_CONFIG */
if ((p= getenv("MARIADB_CONFIG")))
{
if (!stat(p, &s) && S_ISREG(s.st_mode))
{
goto end;
}
}
/* Try to determine path of executable */
if (!(p= alloca(PATH_MAX)))
goto end;
else {
#if defined(__APPLE__)
// If reading the path was successful, then *bufsize is
// unchanged.
unsigned int len= PATH_MAX - 1;
if (_NSGetExecutablePath(p, &len) != 0)
*p= 0;
else
{
p[len]= 0;
if (realpath(p, p) != 0)
*p= 0;
}
#elif defined(__sun) || defined(SOLARIS)
if (realpath(getexecname(), p) == NULL)
*p= 0;
#elif defined(__NetBSD__)
ssize_t len= readlink("/proc/curproc/exe", p, PATH_MAX);
if (len == -1 || len == PATH_MAX)
*p= 0;
else
p[len]= 0;
#elif defined(__FreeBSD__) || defined(__DragonFly__)
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
size_t cb = PATH_MAX;
if (sysctl(mib, 4, p, &cb, NULL, 0) == -1)
*p= 0;
else
p[cb]= 0;
#elif defined(__linux__)
ssize_t len= readlink("/proc/self/exe", p, PATH_MAX);
if (len == -1 || len == PATH_MAX)
*p= 0;
else
p[len]= 0;
#else
*p= 0;
#endif
}
end:
if (p && p[0])
{
char *c, *search= alloca(6 + strlen(mariadb_progname));
sprintf(search, "/bin/%s", mariadb_progname);
c= strstr(p, search);
if (c)
{
strncpy(installation_dir, p, c - p);
}
else
*p=0;
}
if (!p || !p[0])
{
strncpy(installation_dir, "/usr/local", PATH_MAX - 1);
return;
}
}
int main(int argc, char **argv)
{
int c;
char *p = strrchr(argv[0], '/');
mariadb_progname= p ? p + 1 : argv[0];
mariadb_get_install_location();
if (argc <= 1)
{
usage();
exit(0);
}
while(1)
{
int option_index= 0;
c= getopt_long(argc, argv, "abcdefghijklmno", long_options, &option_index);
switch(c) {
case 'a': /* CFLAGS and Include directories */
printf(CFLAGS, installation_dir, installation_dir);
break;
case 'b': /* Usage */
usage();
break;
case 'c': /* Include directories */
printf(INCLUDE, installation_dir, installation_dir);
break;
case 'd': /* Library directories and names */
case 'e':
printf(LIBS, installation_dir);
break;
case 'f': /* Server version */
printf(VERSION);
break;
case 'g': /* Connector/C version */
printf(CC_VERSION);
break;
case 'h': /* Unix socket */
printf(SOCKET);
break;
case 'i': /* default port */
printf(PORT);
break;
case 'j': /* plugin directory */
printf(PLUGIN_DIR, installation_dir);
break;
case 'k': /* TLS version */
printf("%s", TLS_LIBRARY_VERSION);
break;
case 'l': /* System libraries */
printf(LIBS_SYS);
break;
case 'm': /* variable */
{
int i= 0;
while (variables[i].variable)
{
if (!strcmp(optarg, variables[i].variable))
{
printf(variables[i].value, installation_dir);
break;
}
i++;
}
if (!variables[i].variable)
{
printf("Unknown variable '%s'\n", optarg);
exit(1);
}
break;
}
#ifdef HAVE_EMBEDDED
case 'n':
puts(EMBEDDED_LIBS);
break;
#endif
default:
exit((c != -1));
}
printf("\n");
}
exit(0);
}

17
vendor/mariadb/client/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,17 @@
INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include)
IF(WIN32)
SET_VERSION_INFO("TARGET:mariadb_client_plugin_info"
"FILE_TYPE:VFT_APP"
"SOURCE_FILE:client/ma_plugin_info.c"
"ORIGINAL_FILE_NAME:mariadb_client_plugin_info.exe"
"FILE_DESCRIPTION:Client plugin viewer")
ENDIF()
ADD_EXECUTABLE(mariadb_client_plugin_info ${mariadb_client_plugin_info_RC} ma_plugin_info.c)
TARGET_LINK_LIBRARIES(mariadb_client_plugin_info mariadbclient)
INSTALL(TARGETS mariadb_client_plugin_info
DESTINATION ${INSTALL_BINDIR}
COMPONENT SharedLibraries)
SIGN_TARGET(mariadb_client_plugin_info)

211
vendor/mariadb/client/ma_plugin_info.c vendored Normal file
View file

@ -0,0 +1,211 @@
#include <my_global.h>
#include <my_sys.h>
#include <mysql.h>
#include <mysql/client_plugin.h>
#include <getopt.h>
#include <stdio.h>
#include <my_dir.h>
#include <ma_string.h>
#define CLIENT_PLUGIN_INFO_VERSION "1.0.0"
static struct option long_options[]=
{
{"all", no_argument, 0, 'a'},
{"builtin", no_argument, 0, 'b'},
{"dynamic", no_argument, 0, 'd'},
{"directory", 1, 0, 'p'},
{"plugin_name", 1, 0, 'n'},
{"version", no_argument, 0, 'v'},
{"help", no_argument, 0, '?'},
{NULL, 0, 0, 0}
};
static char *values[] =
{
"show information for all plugins",
"show information for builtin plugins",
"show information for dynamic plugins",
"show information for dynamic plugins in specified directory",
"show information for specified plugin",
"show version information",
"display this help and exit",
NULL
};
struct st_plugin_type
{
int type;
char *typename;
};
#ifndef _WIN32
int my_errno=0;
#endif
static struct st_plugin_type plugin_types[]=
{
{MYSQL_CLIENT_AUTHENTICATION_PLUGIN, "authentication"},
{MARIADB_CLIENT_PVIO_PLUGIN, "virtual IO"},
{MARIADB_CLIENT_TRACE_PLUGIN, "trace"},
{MARIADB_CLIENT_REMOTEIO_PLUGIN, "remote file access"},
{MARIADB_CLIENT_CONNECTION_PLUGIN, "connection handler"},
{0, "unknown"}
};
static void version()
{
printf("%s Version %s\n", ma_progname, CLIENT_PLUGIN_INFO_VERSION);
}
static void usage(void)
{
int i=0;
printf("%s Version %s\n", ma_progname, CLIENT_PLUGIN_INFO_VERSION);
puts("Copyright 2015 MariaDB Corporation AB");
puts("Show client plugin information for MariaDB Connector/C.");
printf("Usage: %s [OPTIONS] [plugin_name]\n", ma_progname);
while (long_options[i].name)
{
printf(" --%-12s -%s\n", long_options[i].name, values[i]);
i++;
}
}
static char *ma_get_type_name(int type)
{
int i=0;
while (plugin_types[i].type)
{
if (type== plugin_types[i].type)
return plugin_types[i].typename;
i++;
}
return plugin_types[i].typename;
}
static void show_plugin_info(struct st_mysql_client_plugin *plugin, my_bool builtin)
{
printf("Name: %s\n", plugin->name);
printf("Type: %s\n", ma_get_type_name(plugin->type));
printf("Desc: %s\n", plugin->desc);
printf("Author: %s\n", plugin->author);
printf("License: %s\n", plugin->license);
printf("Version: %d.%d.%d\n", plugin->version[0], plugin->version[1], plugin->version[2]);
printf("API Version: 0x%04X\n", plugin->interface_version);
printf("Build type: %s\n", builtin ? "builtin" : "dynamic");
printf("\n");
}
static void show_builtin()
{
struct st_mysql_client_plugin **builtin;
for (builtin= mysql_client_builtins; *builtin; builtin++)
show_plugin_info(*builtin, TRUE);
}
static void show_file(char *filename)
{
char dlpath[FN_REFLEN+1];
void *sym, *dlhandle;
struct st_mysql_client_plugin *plugin;
char *env_plugin_dir= getenv("MARIADB_PLUGIN_DIR");
char *has_so_ext= strstr(filename, SO_EXT);
if (!strchr(filename, FN_LIBCHAR))
snprintf(dlpath, sizeof(dlpath) - 1, "%s/%s%s",
(env_plugin_dir) ? env_plugin_dir : PLUGINDIR,
filename,
has_so_ext ? "" : SO_EXT);
else
strcpy(dlpath, filename);
if ((dlhandle= dlopen((const char *)dlpath, RTLD_NOW)))
{
if (sym= dlsym(dlhandle, plugin_declarations_sym))
{
plugin= (struct st_mysql_client_plugin *)sym;
show_plugin_info(plugin, 0);
}
dlclose(dlhandle);
}
}
static void show_dynamic(const char *directory)
{
MY_DIR *dir= NULL;
unsigned int i;
char *plugin_dir= directory ? (char *)directory : getenv("MARIADB_PLUGIN_DIR");
if (!plugin_dir)
plugin_dir= PLUGINDIR;
printf("plugin_dir %s\n", plugin_dir);
dir= my_dir(plugin_dir, 0);
if (!dir || !dir->number_off_files)
{
printf("No plugins found in %s\n", plugin_dir);
goto end;
}
for (i=0; i < dir->number_off_files; i++)
{
char *p= strstr(dir->dir_entry[i].name, SO_EXT);
if (p)
show_file(dir->dir_entry[i].name);
}
end:
if (dir)
my_dirend(dir);
}
int main(int argc, char *argv[])
{
int option_index= 0;
int c;
ma_progname= argv[0];
mysql_server_init(0, NULL, NULL);
if (argc <= 1)
{
usage();
exit(1);
}
c= getopt_long(argc, argv, "bdapnvh?", long_options, &option_index);
switch(c) {
case 'a': /* all */
show_builtin();
show_dynamic(NULL);
break;
case 'b': /* builtin */
show_builtin();
break;
case 'd': /* dynamic */
show_dynamic(NULL);
break;
case 'v':
version();
break;
case 'n':
if (argc > 2)
show_file(argv[2]);
break;
case 'p':
if (argc > 2)
show_dynamic(argv[2]);
break;
case '?':
usage();
break;
default:
printf("unrecognized option: %s", argv[1]);
exit(1);
}
exit(0);
}

View file

@ -0,0 +1,22 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,34 @@
#
# Copyright (C) 2013-2016 MariaDB Corporation AB
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the COPYING-CMAKE-SCRIPTS file.
#
MACRO(GET_CONNECTOR_PACKAGE_NAME name)
# check if we have 64bit
IF(SIZEOF_VOIDP EQUAL 8)
SET(IS64 1)
ENDIF()
SET (PLATFORM_NAME ${CMAKE_SYSTEM_NAME})
SET (MACHINE_NAME ${CMAKE_SYSTEM_PROCESSOR})
SET (CONCAT_SIGN "-")
IF(CMAKE_SYSTEM_NAME MATCHES "Windows")
SET(PLATFORM_NAME "win")
SET(CONCAT_SIGN "")
IF(IS64)
IF(CMAKE_C_COMPILER_ARCHITECTURE_ID)
STRING(TOLOWER "${CMAKE_C_COMPILER_ARCHITECTURE_ID}" MACHINE_NAME)
ELSE()
SET(MACHINE_NAME x64)
ENDIF()
ELSE()
SET(MACHINE_NAME "32")
ENDIF()
ENDIF()
SET(product_name "mysql-connector-c-${CPACK_PACKAGE_VERSION}-${PLATFORM_NAME}${CONCAT_SIGN}${MACHINE_NAME}")
STRING(TOLOWER ${product_name} ${name})
ENDMACRO()

124
vendor/mariadb/cmake/FindGSSAPI.cmake vendored Normal file
View file

@ -0,0 +1,124 @@
#
# Copyright (C) 2013-2016 MariaDB Corporation AB
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the COPYING-CMAKE-SCRIPTS file.
#
# - Try to detect the GSSAPI support
# Once done this will define
#
# GSSAPI_FOUND - system supports GSSAPI
# GSSAPI_INCS - the GSSAPI include directory
# GSSAPI_LIBS - the libraries needed to use GSSAPI
# GSSAPI_FLAVOR - the type of API - MIT or HEIMDAL
# Copyright (c) 2006, Pino Toscano, <toscano.pino@tiscali.it>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if(GSSAPI_LIBS AND GSSAPI_FLAVOR)
# in cache already
set(GSSAPI_FOUND TRUE)
else()
find_program(KRB5_CONFIG NAMES krb5-config PATHS
/opt/local/bin
/usr/lib/mit/bin/
ONLY_CMAKE_FIND_ROOT_PATH # this is required when cross compiling with cmake 2.6 and ignored with cmake 2.4, Alex
)
mark_as_advanced(KRB5_CONFIG)
#reset vars
set(GSSAPI_INCS)
set(GSSAPI_LIBS)
set(GSSAPI_FLAVOR)
if(KRB5_CONFIG)
set(HAVE_KRB5_GSSAPI TRUE)
execute_process(
COMMAND ${KRB5_CONFIG} --libs gssapi
RESULT_VARIABLE _return_VALUE
OUTPUT_VARIABLE GSSAPI_LIBS
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(_return_VALUE)
message(STATUS "GSSAPI configure check failed.")
set(HAVE_KRB5_GSSAPI FALSE)
endif()
IF(CMAKE_SYSTEM_NAME MATCHES AIX)
string(REGEX REPLACE "-Wl[A-Za-z0-9_/,:-]*[ $]?" "" GSSAPI_LIBS "${GSSAPI_LIBS}")
string(REGEX REPLACE "-L[A-Za-z0-9_/,:-]*[ $]?" "" GSSAPI_LIBS "${GSSAPI_LIBS}")
ENDIF()
execute_process(
COMMAND ${KRB5_CONFIG} --cflags gssapi
RESULT_VARIABLE _return_VALUE
OUTPUT_VARIABLE GSSAPI_INCS
OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REGEX REPLACE "(\r?\n)+$" "" GSSAPI_INCS "${GSSAPI_INCS}")
string(REGEX REPLACE " *-I" ";" GSSAPI_INCS "${GSSAPI_INCS}")
execute_process(
COMMAND ${KRB5_CONFIG} --vendor
RESULT_VARIABLE _return_VALUE
OUTPUT_VARIABLE gssapi_flavor_tmp
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(GSSAPI_FLAVOR_MIT)
if(gssapi_flavor_tmp MATCHES ".*Massachusetts.*")
set(GSSAPI_FLAVOR "MIT")
else()
set(GSSAPI_FLAVOR "HEIMDAL")
endif()
if(NOT HAVE_KRB5_GSSAPI)
if (gssapi_flavor_tmp MATCHES "Sun Microsystems.*")
message(STATUS "Solaris Kerberos does not have GSSAPI; this is normal.")
set(GSSAPI_LIBS)
set(GSSAPI_INCS)
else()
message(WARNING "${KRB5_CONFIG} failed unexpectedly.")
endif()
endif()
if(GSSAPI_LIBS) # GSSAPI_INCS can be also empty, so don't rely on that
set(GSSAPI_FOUND TRUE CACHE STRING "")
message(STATUS "Found GSSAPI: ${GSSAPI_LIBS}")
set(GSSAPI_INCS ${GSSAPI_INCS} CACHE STRING "")
set(GSSAPI_LIBS ${GSSAPI_LIBS} CACHE STRING "")
set(GSSAPI_FLAVOR ${GSSAPI_FLAVOR} CACHE STRING "")
mark_as_advanced(GSSAPI_INCS GSSAPI_LIBS GSSAPI_FLAVOR)
endif()
endif()
endif()

17
vendor/mariadb/cmake/FindHogweed.cmake vendored Normal file
View file

@ -0,0 +1,17 @@
# - Find Hogweed
#
# HOGWEED_LIBRARIES - List of libraries when using libhogweed.
# HOGWEED_FOUND - True if libhogweed found.
IF (HOGWEED_FOUND)
SET(HOGWEED_FIND_QUIETLY TRUE)
ENDIF()
FIND_LIBRARY(HOGWEED_LIBRARY NAMES hogweed libhogweed)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(HOGWEED DEFAULT_MSG HOGWEED_LIBRARY)
IF(HOGWEED_FOUND)
SET(HOGWEED_LIBRARIES ${HOGWEED_LIBRARY})
ENDIF()

82
vendor/mariadb/cmake/FindIconv.cmake vendored Normal file
View file

@ -0,0 +1,82 @@
#
# Copyright (C) 2010 Michael Bell <michael.bell@web.de>
# 2015-2016 MariaDB Corporation AB
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the COPYING-CMAKE-SCRIPTS file.
#
# ICONV_EXTERNAL - Iconv is an external library (not libc)
# ICONV_FOUND - system has Iconv
# ICONV_INCLUDE_DIR - the Iconv include directory
# ICONV_LIBRARIES - Link these to use Iconv
# ICONV_SECOND_ARGUMENT_IS_CONST - the second argument for iconv() is const
# ICONV_VERSION - Iconv version string
if (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
# Already in cache, be silent
set(ICONV_FIND_QUIETLY TRUE)
endif ()
find_path(ICONV_INCLUDE_DIR iconv.h)
IF(CMAKE_SYSTEM_NAME MATCHES "SunOS")
# There is some libiconv.so in /usr/local that must
# be avoided, iconv routines are in libc
ELSEIF(APPLE)
find_library(ICONV_LIBRARIES NAMES iconv libiconv PATHS
/usr/lib/
NO_CMAKE_SYSTEM_PATH)
SET(ICONV_EXTERNAL TRUE)
ELSE()
find_library(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2)
IF(ICONV_LIBRARIES)
SET(ICONV_EXTERNAL TRUE)
ENDIF()
ENDIF()
if (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
set (ICONV_FOUND TRUE)
endif ()
set(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
IF(ICONV_EXTERNAL)
set(CMAKE_REQUIRED_LIBRARIES ${ICONV_LIBRARIES})
ENDIF()
if (ICONV_FOUND)
include(CheckCSourceCompiles)
CHECK_C_SOURCE_COMPILES("
#include <iconv.h>
int main(){
iconv_t conv = 0;
const char* in = 0;
size_t ilen = 0;
char* out = 0;
size_t olen = 0;
iconv(conv, &in, &ilen, &out, &olen);
return 0;
}
" ICONV_SECOND_ARGUMENT_IS_CONST )
add_compile_definitions(HAVE_ICONV)
endif ()
set (CMAKE_REQUIRED_INCLUDES)
set (CMAKE_REQUIRED_LIBRARIES)
if (ICONV_FOUND)
if (NOT ICONV_FIND_QUIETLY)
message (STATUS "Found Iconv: ${ICONV_LIBRARIES}")
endif ()
else ()
if (Iconv_FIND_REQUIRED)
message (FATAL_ERROR "Could not find Iconv")
endif ()
endif ()
MARK_AS_ADVANCED(
ICONV_INCLUDE_DIR
ICONV_LIBRARIES
ICONV_EXTERNAL
ICONV_SECOND_ARGUMENT_IS_CONST
)

19
vendor/mariadb/cmake/FindNettle.cmake vendored Normal file
View file

@ -0,0 +1,19 @@
# - Find Nettle
#
# NETTLE_INCLUDE_DIR - where to find <nettle/sha.h>, etc.
# NETTLE_LIBRARIES - List of libraries when using libnettle.
# NETTLE_FOUND - True if libnettle found.
IF (NETTLE_INCLUDE_DIR)
SET(NETTLE_FIND_QUIETLY TRUE)
ENDIF()
FIND_PATH(NETTLE_INCLUDE_DIR nettle/md5.h nettle/ripemd160.h nettle/sha.h)
FIND_LIBRARY(NETTLE_LIBRARY NAMES nettle libnettle)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(NETTLE DEFAULT_MSG NETTLE_LIBRARY NETTLE_INCLUDE_DIR)
IF(NETTLE_FOUND)
SET(NETTLE_LIBRARIES ${NETTLE_LIBRARY})
ENDIF()

21
vendor/mariadb/cmake/FindZStd.cmake vendored Normal file
View file

@ -0,0 +1,21 @@
# - Find zstd
# Find the zstd compression library and includes
#
# ZSTD_INCLUDE_DIRS - where to find zstd.h, etc.
# ZSTD_LIBRARIES - List of libraries when using zstd.
# ZSTD_FOUND - True if zstd found.
find_path(ZSTD_INCLUDE_DIRS
NAMES zstd.h
HINTS ${ZSTD_ROOT_DIR}/include)
find_library(ZSTD_LIBRARIES
NAMES zstd zstd_static
HINTS ${ZSTD_ROOT_DIR}/lib)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ZSTD DEFAULT_MSG ZSTD_LIBRARIES ZSTD_INCLUDE_DIRS)
mark_as_advanced(
ZSTD_LIBRARIES
ZSTD_INCLUDE_DIRS)

View file

@ -0,0 +1,29 @@
#
# Copyright (C) 2013-2016 MariaDB Corporation AB
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the COPYING-CMAKE-SCRIPTS file.
#
INCLUDE(CheckFunctionExists)
INCLUDE(CheckLibraryExists)
FUNCTION(SEARCH_LIBRARY library_name function liblist)
IF(${${library_name}})
RETURN()
ENDIF()
CHECK_FUNCTION_EXISTS(${function} IS_${function}_LIBC_FUNC)
IF(IS_${function}_LIBC_FUNC)
SET(${library_name} "" PARENT_SCOPE)
RETURN()
ENDIF()
FOREACH(lib ${liblist})
CHECK_LIBRARY_EXISTS(${lib} ${function} "" HAVE_${function}_IN_${lib})
IF(HAVE_${function}_IN_${lib})
SET(${library_name} ${lib} PARENT_SCOPE)
SET(HAVE_${library_name} 1 PARENT_SCOPE)
RETURN()
ENDIF()
ENDFOREACH()
ENDFUNCTION()

385
vendor/mariadb/cmake/WindowsCache.cmake vendored Normal file
View file

@ -0,0 +1,385 @@
#
# Copyright (C) 2013-2016 MariaDB Corporation AB
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the COPYING-CMAKE-SCRIPTS file.
#
IF(MSVC)
SET(BFD_H_EXISTS 0 CACHE INTERNAL "")
SET(HAVE_ACCESS 1 CACHE INTERNAL "")
SET(HAVE_AIO_H CACHE INTERNAL "")
SET(HAVE_AIO_READ CACHE INTERNAL "")
SET(HAVE_ALARM CACHE INTERNAL "")
SET(HAVE_ALLOCA_H CACHE INTERNAL "")
SET(HAVE_ARPA_INET_H CACHE INTERNAL "")
SET(HAVE_ASM_MSR_H CACHE INTERNAL "")
SET(HAVE_BACKTRACE CACHE INTERNAL "")
SET(HAVE_BACKTRACE_SYMBOLS CACHE INTERNAL "")
SET(HAVE_BACKTRACE_SYMBOLS_FD CACHE INTERNAL "")
SET(HAVE_BFILL CACHE INTERNAL "")
SET(HAVE_BMOVE CACHE INTERNAL "")
SET(HAVE_BSD_SIGNALS CACHE INTERNAL "")
SET(HAVE_BSEARCH 1 CACHE INTERNAL "")
SET(HAVE_BSS_START CACHE INTERNAL "")
SET(HAVE_BZERO CACHE INTERNAL "")
SET(HAVE_CHOWN CACHE INTERNAL "")
SET(HAVE_CLOCK_GETTIME CACHE INTERNAL "")
SET(HAVE_COMPRESS CACHE INTERNAL "")
SET(HAVE_CRYPT CACHE INTERNAL "")
SET(HAVE_CRYPT_H CACHE INTERNAL "")
SET(HAVE_CUSERID CACHE INTERNAL "")
SET(HAVE_CXX_NEW 1 CACHE INTERNAL "")
SET(HAVE_DECL_MADVISE CACHE INTERNAL "")
SET(HAVE_DIRECTIO CACHE INTERNAL "")
SET(HAVE_DIRENT_H CACHE INTERNAL "")
SET(HAVE_DLERROR CACHE INTERNAL "")
SET(HAVE_DLFCN_H CACHE INTERNAL "")
SET(HAVE_DLOPEN CACHE INTERNAL "")
SET(HAVE_DOPRNT CACHE INTERNAL "")
SET(HAVE_EXECINFO_H CACHE INTERNAL "")
SET(HAVE_FCHMOD CACHE INTERNAL "")
SET(HAVE_FCNTL CACHE INTERNAL "")
SET(HAVE_FCNTL_H 1 CACHE INTERNAL "")
SET(HAVE_FCNTL_NONBLOCK CACHE INTERNAL "")
SET(HAVE_FCONVERT CACHE INTERNAL "")
SET(HAVE_FDATASYNC CACHE INTERNAL "")
SET(HAVE_DECL_FDATASYNC CACHE INTERNAL "")
SET(HAVE_FEDISABLEEXCEPT CACHE INTERNAL "")
SET(HAVE_FENV_H CACHE INTERNAL "")
SET(HAVE_FESETROUND CACHE INTERNAL "")
SET(HAVE_FGETLN CACHE INTERNAL "")
SET(HAVE_FINITE CACHE INTERNAL "")
SET(HAVE_FINITE_IN_MATH_H CACHE INTERNAL "")
SET(HAVE_FLOATINGPOINT_H CACHE INTERNAL "")
SET(HAVE_FLOAT_H 1 CACHE INTERNAL "")
SET(HAVE_FLOCKFILE CACHE INTERNAL "")
SET(HAVE_FNMATCH_H CACHE INTERNAL "")
SET(HAVE_FPSETMASK CACHE INTERNAL "")
SET(HAVE_FPU_CONTROL_H CACHE INTERNAL "")
SET(HAVE_FSEEKO CACHE INTERNAL "")
SET(HAVE_FSYNC CACHE INTERNAL "")
SET(HAVE_FTIME 1 CACHE INTERNAL "")
SET(HAVE_FTRUNCATE CACHE INTERNAL "")
SET(HAVE_GETADDRINFO 1 CACHE INTERNAL "")
SET(HAVE_GETCWD 1 CACHE INTERNAL "")
SET(HAVE_GETHOSTBYADDR_R CACHE INTERNAL "")
SET(HAVE_GETHRTIME CACHE INTERNAL "")
SET(HAVE_GETLINE CACHE INTERNAL "")
SET(HAVE_GETNAMEINFO CACHE INTERNAL "")
SET(HAVE_GETPAGESIZE CACHE INTERNAL "")
SET(HAVE_GETPASS CACHE INTERNAL "")
SET(HAVE_GETPASSPHRASE CACHE INTERNAL "")
SET(HAVE_GETPWNAM CACHE INTERNAL "")
SET(HAVE_GETPWUID CACHE INTERNAL "")
SET(HAVE_GETRLIMIT CACHE INTERNAL "")
SET(HAVE_GETRUSAGE CACHE INTERNAL "")
SET(HAVE_GETTIMEOFDAY CACHE INTERNAL "")
SET(HAVE_GETWD CACHE INTERNAL "")
SET(HAVE_GRP_H CACHE INTERNAL "")
SET(HAVE_IA64INTRIN_H CACHE INTERNAL "")
SET(HAVE_IEEEFP_H CACHE INTERNAL "")
SET(HAVE_INDEX CACHE INTERNAL "")
SET(HAVE_INITGROUPS CACHE INTERNAL "")
SET(HAVE_INTTYPES_H CACHE INTERNAL "")
SET(HAVE_IPPROTO_IPV6 CACHE INTERNAL "")
SET(HAVE_IPV6 TRUE CACHE INTERNAL "")
SET(HAVE_IPV6_V6ONLY 1 CACHE INTERNAL "")
SET(HAVE_ISINF CACHE INTERNAL "")
SET(HAVE_ISSETUGID CACHE INTERNAL "")
SET(HAVE_GETUID CACHE INTERNAL "")
SET(HAVE_GETEUID CACHE INTERNAL "")
SET(HAVE_GETGID CACHE INTERNAL "")
SET(HAVE_GETEGID CACHE INTERNAL "")
SET(HAVE_LANGINFO_H CACHE INTERNAL "")
SET(HAVE_LDIV 1 CACHE INTERNAL "")
SET(HAVE_LIMITS_H 1 CACHE INTERNAL "")
SET(HAVE_LOCALE_H 1 CACHE INTERNAL "")
SET(HAVE_LOG2 CACHE INTERNAL "")
SET(HAVE_LONGJMP 1 CACHE INTERNAL "")
SET(HAVE_LRAND48 CACHE INTERNAL "")
SET(HAVE_LSTAT CACHE INTERNAL "")
SET(HAVE_MADVISE CACHE INTERNAL "")
SET(HAVE_MALLINFO CACHE INTERNAL "")
SET(HAVE_MALLOC_H 1 CACHE INTERNAL "")
SET(HAVE_MEMALIGN CACHE INTERNAL "")
SET(HAVE_MEMCPY 1 CACHE INTERNAL "")
SET(HAVE_MEMMOVE 1 CACHE INTERNAL "")
SET(HAVE_MEMORY_H 1 CACHE INTERNAL "")
SET(HAVE_MKSTEMP CACHE INTERNAL "")
SET(HAVE_MLOCK CACHE INTERNAL "")
SET(HAVE_MLOCKALL CACHE INTERNAL "")
SET(HAVE_MMAP CACHE INTERNAL "")
SET(HAVE_MMAP64 CACHE INTERNAL "")
SET(HAVE_NETDB_H CACHE INTERNAL "")
SET(HAVE_NETINET_IN6_H CACHE INTERNAL "")
SET(HAVE_NETINET_IN_H CACHE INTERNAL "")
SET(HAVE_NL_LANGINFO CACHE INTERNAL "")
SET(HAVE_PASE_ENVIRONMENT CACHE INTERNAL "")
SET(HAVE_PATHS_H CACHE INTERNAL "")
SET(HAVE_PCLOSE CACHE INTERNAL "")
SET(HAVE_PERROR 1 CACHE INTERNAL "")
SET(HAVE_PEERCRED CACHE INTERNAL "")
SET(HAVE_PAM_APPL_H CACHE INTERNAL "")
SET(HAVE_POLL_H CACHE INTERNAL "")
SET(HAVE_POPEN CACHE INTERNAL "")
SET(HAVE_POLL CACHE INTERNAL "")
SET(HAVE_PORT_CREATE CACHE INTERNAL "")
SET(HAVE_PORT_H CACHE INTERNAL "")
SET(HAVE_POSIX_FALLOCATE CACHE INTERNAL "")
SET(HAVE_POSIX_SIGNALS CACHE INTERNAL "")
SET(HAVE_PREAD CACHE INTERNAL "")
SET(HAVE_PRINTSTACK CACHE INTERNAL "")
SET(HAVE_PTHREAD_ATTR_CREATE CACHE INTERNAL "")
SET(HAVE_PTHREAD_ATTR_GETSTACKSIZE CACHE INTERNAL "")
SET(HAVE_PTHREAD_ATTR_SETSCOPE CACHE INTERNAL "")
SET(HAVE_PTHREAD_ATTR_SETSTACKSIZE CACHE INTERNAL "")
SET(HAVE_PTHREAD_CONDATTR_CREATE CACHE INTERNAL "")
SET(HAVE_PTHREAD_CONDATTR_SETCLOCK CACHE INTERNAL "")
SET(HAVE_PTHREAD_INIT CACHE INTERNAL "")
SET(HAVE_PTHREAD_KEY_DELETE CACHE INTERNAL "")
SET(HAVE_PTHREAD_RWLOCK_RDLOCK CACHE INTERNAL "")
SET(HAVE_PTHREAD_SIGMASK CACHE INTERNAL "")
SET(HAVE_PTHREAD_THREADMASK CACHE INTERNAL "")
SET(HAVE_PTHREAD_YIELD_NP CACHE INTERNAL "")
SET(HAVE_PTHREAD_YIELD_ZERO_ARG CACHE INTERNAL "")
SET(HAVE_PUTENV 1 CACHE INTERNAL "")
SET(HAVE_PWD_H CACHE INTERNAL "")
SET(HAVE_RDTSCLL CACHE INTERNAL "")
SET(HAVE_READDIR_R CACHE INTERNAL "")
SET(HAVE_READLINK CACHE INTERNAL "")
SET(HAVE_READ_REAL_TIME CACHE INTERNAL "")
SET(HAVE_REALPATH CACHE INTERNAL "")
SET(HAVE_REGCOMP CACHE INTERNAL "")
SET(HAVE_RENAME 1 CACHE INTERNAL "")
SET(HAVE_RE_COMP CACHE INTERNAL "")
SET(HAVE_RINT CACHE INTERNAL "")
SET(HAVE_RWLOCK_INIT CACHE INTERNAL "")
SET(HAVE_SCHED_H CACHE INTERNAL "")
SET(HAVE_SCHED_YIELD CACHE INTERNAL "")
SET(HAVE_SELECT 1 CACHE INTERNAL "")
SET(HAVE_SELECT_H CACHE INTERNAL "")
SET(HAVE_SEMAPHORE_H CACHE INTERNAL "")
SET(HAVE_SETENV CACHE INTERNAL "")
SET(HAVE_SETFD CACHE INTERNAL "")
SET(HAVE_SETLOCALE 1 CACHE INTERNAL "")
SET(HAVE_SHMAT CACHE INTERNAL "")
SET(HAVE_SHMCTL CACHE INTERNAL "")
SET(HAVE_SHMDT CACHE INTERNAL "")
SET(HAVE_SHMGET CACHE INTERNAL "")
SET(HAVE_SIGACTION CACHE INTERNAL "")
SET(HAVE_SIGADDSET CACHE INTERNAL "")
SET(HAVE_SIGEMPTYSET CACHE INTERNAL "")
SET(HAVE_SIGHOLD CACHE INTERNAL "")
SET(HAVE_SIGINT 1 CACHE INTERNAL "")
SET(HAVE_SIGPIPE CACHE INTERNAL "")
SET(HAVE_SIGQUIT CACHE INTERNAL "")
SET(HAVE_SIGSET CACHE INTERNAL "")
SET(HAVE_SIGTERM 1 CACHE INTERNAL "")
SET(HAVE_SIGTHREADMASK CACHE INTERNAL "")
SET(HAVE_SIGWAIT CACHE INTERNAL "")
SET(HAVE_SIZEOF_BOOL FALSE CACHE INTERNAL "")
SET(HAVE_SIZEOF_CHAR TRUE CACHE INTERNAL "")
SET(SIZEOF_CHAR 1 CACHE INTERNAL "")
SET(HAVE_SIZEOF_CHARP TRUE CACHE INTERNAL "")
SET(SIZEOF_CHARP ${CMAKE_SIZEOF_VOID_P} CACHE INTERNAL "")
SET(HAVE_SIZEOF_IN6_ADDR TRUE CACHE INTERNAL "")
SET(HAVE_SIZEOF_INT TRUE CACHE INTERNAL "")
SET(SIZEOF_INT 4 CACHE INTERNAL "")
SET(HAVE_SIZEOF_INT16 FALSE CACHE INTERNAL "")
SET(HAVE_SIZEOF_INT32 FALSE CACHE INTERNAL "")
SET(HAVE_SIZEOF_INT64 FALSE CACHE INTERNAL "")
SET(HAVE_SIZEOF_INT8 FALSE CACHE INTERNAL "")
SET(HAVE_SIZEOF_LONG TRUE CACHE INTERNAL "")
SET(SIZEOF_LONG 4 CACHE INTERNAL "")
SET(HAVE_SIZEOF_LONG_LONG TRUE CACHE INTERNAL "")
SET(SIZEOF_LONG_LONG 8 CACHE INTERNAL "")
SET(HAVE_SIZEOF_MODE_T FALSE CACHE INTERNAL "")
SET(HAVE_SIZEOF_OFF_T TRUE CACHE INTERNAL "")
SET(SIZEOF_OFF_T 4 CACHE INTERNAL "")
SET(HAVE_SIZEOF_SHORT TRUE CACHE INTERNAL "")
SET(SIZEOF_SHORT 2 CACHE INTERNAL "")
SET(HAVE_SIZEOF_SIGSET_T FALSE CACHE INTERNAL "")
SET(HAVE_SIZEOF_SIZE_T TRUE CACHE INTERNAL "")
SET(SIZEOF_SIZE_T ${CMAKE_SIZEOF_VOID_P} CACHE INTERNAL "")
SET(HAVE_SIZEOF_SOCKADDR_IN6 TRUE CACHE INTERNAL "")
SET(HAVE_SIZEOF_SOCKLEN_T FALSE CACHE INTERNAL "")
SET(HAVE_SIZEOF_UCHAR FALSE CACHE INTERNAL "")
SET(HAVE_SIZEOF_UINT FALSE CACHE INTERNAL "")
SET(HAVE_SIZEOF_UINT16 FALSE CACHE INTERNAL "")
SET(HAVE_SIZEOF_UINT32 FALSE CACHE INTERNAL "")
SET(HAVE_SIZEOF_UINT64 FALSE CACHE INTERNAL "")
SET(HAVE_SIZEOF_UINT8 FALSE CACHE INTERNAL "")
SET(HAVE_SIZEOF_ULONG FALSE CACHE INTERNAL "")
SET(HAVE_SIZEOF_U_INT32_T FALSE CACHE INTERNAL "")
SET(HAVE_SIZE_OF_SSIZE_T FALSE CACHE INTERNAL "")
SET(HAVE_SLEEP CACHE INTERNAL "")
SET(HAVE_SOCKADDR_STORAGE_SS_FAMILY 1 CACHE INTERNAL "")
SET(HAVE_SOLARIS_STYLE_GETHOST CACHE INTERNAL "")
SET(STACK_DIRECTION -1 CACHE INTERNAL "")
SET(HAVE_STDARG_H 1 CACHE INTERNAL "")
SET(HAVE_STDDEF_H 1 CACHE INTERNAL "")
SET(HAVE_STDINT_H CACHE INTERNAL "")
SET(HAVE_STDLIB_H 1 CACHE INTERNAL "")
SET(HAVE_STPCPY CACHE INTERNAL "")
SET(HAVE_STRCASECMP CACHE INTERNAL "")
SET(HAVE_STRCOLL 1 CACHE INTERNAL "")
SET(HAVE_STRDUP 1 CACHE INTERNAL "")
SET(HAVE_STRERROR 1 CACHE INTERNAL "")
SET(HAVE_STRINGS_H CACHE INTERNAL "")
SET(HAVE_STRING_H 1 CACHE INTERNAL "")
SET(HAVE_STRLCAT CACHE INTERNAL "")
SET(HAVE_STRLCPY CACHE INTERNAL "")
SET(HAVE_STRNCASECMP CACHE INTERNAL "")
SET(HAVE_STRNDUP CACHE INTERNAL "")
SET(HAVE_STRNLEN 1 CACHE INTERNAL "")
SET(HAVE_STRPBRK 1 CACHE INTERNAL "")
SET(HAVE_STRSEP CACHE INTERNAL "")
SET(HAVE_STRSIGNAL CACHE INTERNAL "")
SET(HAVE_STRSTR 1 CACHE INTERNAL "")
SET(HAVE_STRTOK_R CACHE INTERNAL "")
SET(HAVE_STRTOL 1 CACHE INTERNAL "")
SET(HAVE_STRTOLL CACHE INTERNAL "")
SET(HAVE_STRTOUL 1 CACHE INTERNAL "")
SET(HAVE_STRTOULL CACHE INTERNAL "")
SET(HAVE_SVR3_SIGNALS CACHE INTERNAL "")
SET(HAVE_SYNCH_H CACHE INTERNAL "")
SET(HAVE_SYSENT_H CACHE INTERNAL "")
SET(HAVE_SYS_CDEFS_H CACHE INTERNAL "")
SET(HAVE_SYS_DIR_H CACHE INTERNAL "")
SET(HAVE_SYS_ERRLIST CACHE INTERNAL "")
SET(HAVE_SYS_FILE_H CACHE INTERNAL "")
SET(HAVE_SYS_FPU_H CACHE INTERNAL "")
SET(HAVE_SYS_IOCTL_H CACHE INTERNAL "")
SET(HAVE_SYS_IPC_H CACHE INTERNAL "")
SET(HAVE_SYS_MALLOC_H CACHE INTERNAL "")
SET(HAVE_SYS_MMAN_H CACHE INTERNAL "")
SET(HAVE_SYS_PARAM_H CACHE INTERNAL "")
SET(HAVE_SYS_PRCTL_H CACHE INTERNAL "")
SET(HAVE_SYS_PTEM_H CACHE INTERNAL "")
SET(HAVE_SYS_PTE_H CACHE INTERNAL "")
SET(HAVE_SYS_RESOURCE_H CACHE INTERNAL "")
SET(HAVE_SYS_SELECT_H CACHE INTERNAL "")
SET(HAVE_SYS_SHM_H CACHE INTERNAL "")
SET(HAVE_SYS_SOCKIO_H CACHE INTERNAL "")
SET(HAVE_SYS_SOCKET_H CACHE INTERNAL "")
SET(HAVE_SYS_STAT_H 1 CACHE INTERNAL "")
SET(HAVE_SYS_STREAM_H CACHE INTERNAL "")
SET(HAVE_SYS_TERMCAP_H CACHE INTERNAL "")
SET(HAVE_SYS_TIMEB_H 1 CACHE INTERNAL "")
SET(HAVE_SYS_TIMES_H CACHE INTERNAL "")
SET(HAVE_SYS_TIME_H CACHE INTERNAL "")
SET(HAVE_SYS_TYPES_H 1 CACHE INTERNAL "")
SET(HAVE_SYS_UN_H CACHE INTERNAL "")
SET(HAVE_SYS_UTIME_H 1 CACHE INTERNAL "")
SET(HAVE_SYS_VADVISE_H CACHE INTERNAL "")
SET(HAVE_SYS_WAIT_H CACHE INTERNAL "")
SET(HAVE_TCGETATTR CACHE INTERNAL "")
SET(HAVE_TELL 1 CACHE INTERNAL "")
SET(HAVE_TEMPNAM 1 CACHE INTERNAL "")
SET(HAVE_TERMCAP_H CACHE INTERNAL "")
SET(HAVE_TERMIOS_H CACHE INTERNAL "")
SET(HAVE_TERMIO_H CACHE INTERNAL "")
SET(HAVE_TERM_H CACHE INTERNAL "")
SET(HAVE_THR_SETCONCURRENCY CACHE INTERNAL "")
SET(HAVE_THR_YIELD CACHE INTERNAL "")
SET(HAVE_TIME 1 CACHE INTERNAL "")
SET(HAVE_TIMES CACHE INTERNAL "")
SET(HAVE_TIMESPEC_TS_SEC CACHE INTERNAL "")
SET(HAVE_TIME_H 1 CACHE INTERNAL "")
SET(HAVE_TZNAME 1 CACHE INTERNAL "")
SET(HAVE_UNISTD_H CACHE INTERNAL "")
SET(HAVE_UTIME_H CACHE INTERNAL "")
SET(HAVE_VALLOC CACHE INTERNAL "")
SET(HAVE_VARARGS_H 1 CACHE INTERNAL "")
SET(HAVE_VASPRINTF CACHE INTERNAL "")
SET(HAVE_VPRINTF 1 CACHE INTERNAL "")
SET(HAVE_VSNPRINTF 1 CACHE INTERNAL "")
SET(HAVE_WEAK_SYMBOL CACHE INTERNAL "")
SET(HAVE_BIGENDIAN CACHE INTERNAL "")
SET(HAVE__S_IFIFO 1 CACHE INTERNAL "")
SET(HAVE__S_IREAD 1 CACHE INTERNAL "")
SET(HAVE__finite 1 CACHE INTERNAL "")
SET(HAVE__pclose 1 CACHE INTERNAL "")
SET(HAVE__popen 1 CACHE INTERNAL "")
SET(HAVE__stricmp 1 CACHE INTERNAL "")
SET(HAVE__strnicmp 1 CACHE INTERNAL "")
SET(HAVE__strtoi64 1 CACHE INTERNAL "")
SET(HAVE__strtoui64 1 CACHE INTERNAL "")
SET(HAVE_strtok_s 1 CACHE INTERNAL "")
SET(STDC_HEADERS CACHE 1 INTERNAL "")
SET(STRUCT_DIRENT_HAS_D_INO CACHE INTERNAL "")
SET(STRUCT_DIRENT_HAS_D_INO CACHE INTERNAL "")
SET(STRUCT_DIRENT_HAS_D_NAMLEN CACHE INTERNAL "")
SET(TIME_WITH_SYS_TIME CACHE INTERNAL "")
SET(TIME_T_UNSIGNED 1 CACHE INTERNAL "")
SET(TIOCSTAT_IN_SYS_IOCTL CACHE INTERNAL "")
SET(HAVE_S_IROTH CACHE INTERNAL "")
SET(HAVE_S_IFIFO CACHE INTERNAL "")
SET(QSORT_TYPE_IS_VOID 1 CACHE INTERNAL "")
SET(SIGNAL_RETURN_TYPE_IS_VOID 1 CACHE INTERNAL "")
SET(C_HAS_inline CACHE INTERNAL "")
SET(C_HAS___inline 1 CACHE INTERNAL "")
SET(FIONREAD_IN_SYS_IOCTL CACHE INTERNAL "")
SET(FIONREAD_IN_SYS_FILIO CACHE INTERNAL "")
SET(GWINSZ_IN_SYS_IOCTL CACHE INTERNAL "")
SET(HAVE_CXXABI_H CACHE INTERNAL "")
SET(HAVE_NDIR_H CACHE INTERNAL "")
SET(HAVE_SYS_NDIR_H CACHE INTERNAL "")
SET(HAVE_SYS_NDIR_H CACHE INTERNAL "")
SET(HAVE_ASM_TERMBITS_H CACHE INTERNAL "")
SET(HAVE_TERMBITS_H CACHE INTERNAL "")
SET(HAVE_VIS_H CACHE INTERNAL "")
SET(HAVE_WCHAR_H 1 CACHE INTERNAL "")
SET(HAVE_WCTYPE_H 1 CACHE INTERNAL "")
SET(HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP CACHE INTERNAL "")
SET(HAVE_SOCKADDR_IN_SIN_LEN CACHE INTERNAL "")
SET(HAVE_SOCKADDR_IN6_SIN6_LEN CACHE INTERNAL "")
SET(HAVE_VALGRIND CACHE INTERNAL "")
SET(HAVE_EVENT_H CACHE INTERNAL "")
SET(HAVE_LINUX_UNISTD_H CACHE INTERNAL "")
SET(HAVE_SYS_UTSNAME_H CACHE INTERNAL "")
SET(HAVE_PTHREAD_ATTR_GETGUARDSIZE CACHE INTERNAL "")
SET(FIONREAD_IN_SYS_FILIO CACHE INTERNAL "")
SET(FIONREAD_IN_SYS_IOCTL CACHE INTERNAL "")
SET(GWINSZ_IN_SYS_IOCTL CACHE INTERNAL "")
SET(HAVE_ACCESS 1 CACHE INTERNAL "")
SET(HAVE_AIOWAIT CACHE INTERNAL "")
SET(HAVE_AIO_H CACHE INTERNAL "")
SET(HAVE_AIO_READ CACHE INTERNAL "")
SET(HAVE_ALARM CACHE INTERNAL "")
SET(HAVE_ALLOCA CACHE INTERNAL "")
SET(HAVE_ALLOCA_H CACHE INTERNAL "")
SET(HAVE_ARPA_INET_H CACHE INTERNAL "")
SET(HAVE_ASM_MSR_H CACHE INTERNAL "")
SET(HAVE_ASM_TERMBITS_H CACHE INTERNAL "")
SET(HAVE_BACKTRACE CACHE INTERNAL "")
SET(HAVE_BACKTRACE_SYMBOLS CACHE INTERNAL "")
SET(HAVE_BACKTRACE_SYMBOLS_FD CACHE INTERNAL "")
SET(HAVE_BCMP CACHE INTERNAL "")
SET(HAVE_BFILL CACHE INTERNAL "")
SET(HAVE_BMOVE CACHE INTERNAL "")
SET(HAVE_BSD_SIGNALS CACHE INTERNAL "")
SET(HAVE_BSEARCH CACHE INTERNAL "")
SET(HAVE_BSS_START CACHE INTERNAL "")
SET(HAVE_BZERO CACHE INTERNAL "")
SET(HAVE_CHOWN CACHE INTERNAL "")
SET(HAVE_CLOCK_GETTIME CACHE INTERNAL "")
SET(HAVE_COMPRESS CACHE INTERNAL "")
SET(HAVE_CRYPT CACHE INTERNAL "")
SET(HAVE_CRYPT_H CACHE INTERNAL "")
SET(HAVE_CUSERID CACHE INTERNAL "")
SET(HAVE_CXXABI_H CACHE INTERNAL "")
SET(HAVE_DECL_FDATASYNC CACHE INTERNAL "")
SET(HAVE_SIGNAL_H 1 CACHE INTERNAL "")
SET(HAVE_GETHOSTBYNAME_R CACHE INTERNAL "")
SET(HAVE_PTHREAD_ATTR_SETPRIO CACHE INTERNAL "")
SET(HAVE_PTHREAD_ATTR_SETSCHEDPARAM CACHE INTERNAL "")
SET(HAVE_PTHREAD_KILL CACHE INTERNAL "")
SET(HAVE_PTHREAD_SETPRIO_NP CACHE INTERNAL "")
SET(HAVE_PTHREAD_SETSCHEDPARAM CACHE INTERNAL "")
SET(HAVE_SETFILEPOINTER CACHE INTERNAL "")
SET(SIZEOF_U_INT32_T CACHE INTERNAL "")
SET(IS_VOID_SIGNAL 1 CACHE INTERNAL "")
SET(IS_VOID_QSORT 1 CACHE INTERNAL "")
ENDIF()

View file

@ -0,0 +1,30 @@
#
# Copyright (C) 2013-2016 MariaDB Corporation AB
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the COPYING-CMAKE-SCRIPTS file.
#
# This file is included by CMakeLists.txt and
# checks for various functions.
# You will find the appropriate defines in
# include/my_config.h.in
INCLUDE(CheckFunctionExists)
CHECK_FUNCTION_EXISTS (alloca HAVE_ALLOCA)
CHECK_FUNCTION_EXISTS (dlerror HAVE_DLERROR)
CHECK_FUNCTION_EXISTS (dlopen HAVE_DLOPEN)
CHECK_FUNCTION_EXISTS (fcntl HAVE_FCNTL)
CHECK_FUNCTION_EXISTS (memcpy HAVE_MEMCPY)
CHECK_FUNCTION_EXISTS (nl_langinfo HAVE_NL_LANGINFO)
CHECK_FUNCTION_EXISTS (setlocale HAVE_SETLOCALE)
CHECK_FUNCTION_EXISTS (poll HAVE_POLL)
CHECK_FUNCTION_EXISTS (getpwuid HAVE_GETPWUID)
IF(HAVE_FILE_UCONTEXT_H)
CHECK_FUNCTION_EXISTS (makecontext HAVE_UCONTEXT_H)
ENDIF()
CHECK_FUNCTION_EXISTS (cuserid HAVE_CUSERID)

View file

@ -0,0 +1,56 @@
#
# Copyright (C) 2013-2016 MariaDB Corporation AB
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the COPYING-CMAKE-SCRIPTS file.
#
# This file is included by CMakeLists.txt and
# checks for various header files.
# You will find the appropriate defines in
# include/my_config.h.in
INCLUDE(CheckIncludeFiles)
CHECK_INCLUDE_FILES (alloca.h HAVE_ALLOCA_H)
CHECK_INCLUDE_FILES (dlfcn.h HAVE_DLFCN_H)
CHECK_INCLUDE_FILES (fcntl.h HAVE_FCNTL_H)
CHECK_INCLUDE_FILES (float.h HAVE_FLOAT_H)
CHECK_INCLUDE_FILES (limits.h HAVE_LIMITS_H)
CHECK_INCLUDE_FILES (linux/limits.h HAVE_LINUX_LIMITS_H)
CHECK_INCLUDE_FILES (pwd.h HAVE_PWD_H)
CHECK_INCLUDE_FILES (select.h HAVE_SELECT_H)
CHECK_INCLUDE_FILES (signal.h INCLUDE_SIGNAL)
IF(INCLUDE_SIGNAL)
SET(CMAKE_EXTRA_INCLUDE_FILES signal.h)
ENDIF()
CHECK_INCLUDE_FILES (stddef.h HAVE_STDDEF_H)
CHECK_INCLUDE_FILES (stdint.h HAVE_STDINT_H)
IF(HAVE_STDINT_H)
SET(CMAKE_EXTRA_INCLUDE_FILES stdint.h)
ENDIF()
CHECK_INCLUDE_FILES (stdlib.h HAVE_STDLIB_H)
CHECK_INCLUDE_FILES (string.h HAVE_STRING_H)
CHECK_INCLUDE_FILES (sys/ioctl.h HAVE_SYS_IOCTL_H)
CHECK_INCLUDE_FILES (sys/select.h HAVE_SYS_SELECT_H)
CHECK_INCLUDE_FILES (sys/socket.h HAVE_SYS_SOCKET_H)
CHECK_INCLUDE_FILES (sys/types.h HAVE_SYS_TYPES_H)
CHECK_INCLUDE_FILES (sys/stat.h HAVE_SYS_STAT_H)
CHECK_INCLUDE_FILES (sys/un.h HAVE_SYS_UN_H)
CHECK_INCLUDE_FILES (unistd.h HAVE_UNISTD_H)
IF(WITH_BOOST_CONTEXT)
CHECK_INCLUDE_FILE_CXX (boost/fiber/context.hpp HAVE_BOOST_CONTEXT_H)
ENDIF()
IF(APPLE)
SET(CMAKE_REQUIRED_DEFINITIONS -D_XOPEN_SOURCE=600)
ENDIF()
CHECK_INCLUDE_FILES (ucontext.h HAVE_FILE_UCONTEXT_H)
IF(NOT HAVE_FILE_UCONTEXT_H)
CHECK_INCLUDE_FILES (sys/ucontext.h HAVE_FILE_UCONTEXT_H)
ENDIF()

62
vendor/mariadb/cmake/check_types.cmake vendored Normal file
View file

@ -0,0 +1,62 @@
#
# Copyright (C) 2013-2016 MariaDB Corporation AB
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the COPYING-CMAKE-SCRIPTS file.
#
# This file is included by CMakeLists.txt and
# checks for type sizes.
# You will find the appropriate defines in
# include/my_config.h.in
INCLUDE (CheckTypeSize)
SET(CMAKE_EXTRA_INCLUDE_FILES signal.h)
CHECK_TYPE_SIZE("char *" SIZEOF_CHARP)
CHECK_TYPE_SIZE(int SIZEOF_INT)
CHECK_TYPE_SIZE(long SIZEOF_LONG)
CHECK_TYPE_SIZE("long long" SIZEOF_LONG_LONG)
SET(CMAKE_EXTRA_INCLUDE_FILES stdio.h)
CHECK_TYPE_SIZE(size_t SIZEOF_SIZE_T)
SET(CMAKE_EXTRA_INCLUDE_FILES sys/types.h)
CHECK_TYPE_SIZE(uint SIZEOF_UINT)
CHECK_TYPE_SIZE(ushort SIZEOF_USHORT)
CHECK_TYPE_SIZE(ulong SIZEOF_ULONG)
CHECK_TYPE_SIZE(int8 SIZEOF_INT8)
CHECK_TYPE_SIZE(uint8 SIZEOF_UINT8)
CHECK_TYPE_SIZE(int16 SIZEOF_INT16)
CHECK_TYPE_SIZE(uint16 SIZEOF_UINT16)
CHECK_TYPE_SIZE(int32 SIZEOF_INT32)
CHECK_TYPE_SIZE(uint32 SIZEOF_UINT32)
CHECK_TYPE_SIZE(int64 SIZEOF_INT64)
CHECK_TYPE_SIZE(uint64 SIZEOF_UINT64)
CHECK_TYPE_SIZE(socklen_t SIZEOF_SOCKLEN_T)
#
# Compile testing
#
INCLUDE (CheckCSourceCompiles)
#
# SOCKET_SIZE
#
IF(WIN32)
SET(SOCKET_SIZE_TYPE int)
ELSE()
FOREACH(CHECK_TYPE "socklen_t" "size_t" "int")
IF (NOT SOCKET_SIZE_TYPE)
CHECK_C_SOURCE_COMPILES("
#include <sys/socket.h>
int main(int argc, char **argv)
{
getsockname(0, 0, (${CHECK_TYPE} *)0);
return 0;
}"
SOCKET_SIZE_FOUND_${CHECK_TYPE})
IF(SOCKET_SIZE_FOUND_${CHECK_TYPE})
SET(SOCKET_SIZE_TYPE ${CHECK_TYPE})
ENDIF()
ENDIF()
ENDFOREACH()
ENDIF()

30
vendor/mariadb/cmake/export.cmake vendored Normal file
View file

@ -0,0 +1,30 @@
#
# Copyright (C) 2013-2016 MariaDB Corporation AB
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the COPYING-CMAKE-SCRIPTS file.
#
MACRO(CREATE_EXPORT_FILE op outfile version symbols alias_version)
IF(WIN32)
SET(EXPORT_CONTENT "EXPORTS\n")
FOREACH(exp_symbol ${symbols})
SET(EXPORT_CONTENT ${EXPORT_CONTENT} "${exp_symbol}\n")
ENDFOREACH()
ELSE()
SET(EXPORT_CONTENT "VERSION {\n${version} {\nglobal:\n")
FOREACH(exp_symbol ${symbols})
SET(EXPORT_CONTENT "${EXPORT_CONTENT} ${exp_symbol}\\;\n")
ENDFOREACH()
SET(EXPORT_CONTENT "${EXPORT_CONTENT}local:\n *\\;\n}\\;\n")
IF ("${alias_version}" STRGREATER "")
SET(EXPORT_CONTENT "${EXPORT_CONTENT}${alias_version} {\n}\\;\n}\\;\n")
FOREACH(exp_symbol ${symbols})
SET(EXPORT_CONTENT "${EXPORT_CONTENT}\"${exp_symbol}@${alias_version}\" = ${exp_symbol}\\;\n")
ENDFOREACH()
ELSE()
SET(EXPORT_CONTENT "${EXPORT_CONTENT}}\\;\n")
ENDIF()
ENDIF()
FILE(${op} ${CMAKE_CURRENT_BINARY_DIR}/${outfile} ${EXPORT_CONTENT})
ENDMACRO()

160
vendor/mariadb/cmake/install.cmake vendored Normal file
View file

@ -0,0 +1,160 @@
#
# Copyright (C) 2013-2016 MariaDB Corporation AB
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the COPYING-CMAKE-SCRIPTS file.
#
#
# This file contains settings for the following layouts:
#
# - RPM
# Built with default prefix=/usr
#
#
# The following va+riables are used and can be overwritten
#
# INSTALL_LAYOUT installation layout (DEFAULT = standard for tar.gz and zip packages
# RPM packages
#
# INSTALL_BINDIR location of binaries (mariadb_config)
# INSTALL_LIBDIR location of libraries
# INSTALL_PLUGINDIR location of plugins
# INSTALL_MANDIR location of manpages
IF(NOT INSTALL_LAYOUT)
SET(INSTALL_LAYOUT "DEFAULT")
ENDIF()
SET(INSTALL_LAYOUT ${INSTALL_LAYOUT} CACHE
STRING "Installation layout. Currently supported options are DEFAULT (tar.gz and zip), RPM and DEB")
# On Windows we only provide zip and .msi. Latter one uses a different packager.
IF(UNIX)
IF(INSTALL_LAYOUT MATCHES "RPM")
SET(libmariadb_prefix "/usr")
ELSEIF(INSTALL_LAYOUT MATCHES "DEFAULT|DEB")
SET(libmariadb_prefix ${CMAKE_INSTALL_PREFIX})
ENDIF()
ENDIF()
IF(CMAKE_DEFAULT_PREFIX_INITIALIZED_BY_DEFAULT)
SET(CMAKE_DEFAULT_PREFIX ${libmariadb_prefix} CACHE PATH "Installation prefix" FORCE)
ENDIF()
# check if the specified installation layout is valid
SET(VALID_INSTALL_LAYOUTS "DEFAULT" "RPM" "DEB")
LIST(FIND VALID_INSTALL_LAYOUTS "${INSTALL_LAYOUT}" layout_no)
IF(layout_no EQUAL -1)
MESSAGE(FATAL_ERROR "Invalid installation layout ${INSTALL_LAYOUT}. Please specify one of the following layouts: ${VALID_INSTALL_LAYOUTS}")
ENDIF()
#
# Todo: We don't generate man pages yet, will fix it
# later (webhelp to man transformation)
#
#
# DEFAULT layout
#
SET(INSTALL_BINDIR_DEFAULT "bin")
SET(INSTALL_LIBDIR_DEFAULT "lib/mariadb")
SET(INSTALL_PCDIR_DEFAULT "lib/pkgconfig")
SET(INSTALL_INCLUDEDIR_DEFAULT "include/mariadb")
SET(INSTALL_DOCDIR_DEFAULT "docs")
SET(INSTALL_MANDIR_DEFAULT "man")
IF(NOT IS_SUBPROJECT)
SET(INSTALL_PLUGINDIR_DEFAULT "lib/mariadb/plugin")
ELSE()
ENDIF()
SET(LIBMARIADB_STATIC_DEFAULT "mariadbclient")
#
# RPM layout
#
SET(INSTALL_BINDIR_RPM "bin")
IF((CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64le" OR CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "s390x" OR CMAKE_SYSTEM_PROCESSOR MATCHES "riscv64") AND CMAKE_SIZEOF_VOID_P EQUAL 8)
SET(INSTALL_LIBDIR_RPM "lib64/mariadb")
SET(INSTALL_PCDIR_RPM "lib64/pkgconfig")
SET(INSTALL_PLUGINDIR_RPM "lib64/mariadb/plugin")
ELSE()
SET(INSTALL_LIBDIR_RPM "lib/mariadb")
SET(INSTALL_PCDIR_RPM "lib/pkgconfig")
SET(INSTALL_PLUGINDIR_RPM "lib/mariadb/plugin")
ENDIF()
SET(INSTALL_INCLUDEDIR_RPM "include")
SET(INSTALL_DOCDIR_RPM "docs")
SET(INSTALL_MANDIR_RPM "share/man")
SET(LIBMARIADB_STATIC_RPM "mariadbclient")
#
# DEB layout
#
SET(INSTALL_BINDIR_DEB "bin")
SET(INSTALL_LIBDIR_DEB "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
SET(INSTALL_PCDIR_DEB "lib/${CMAKE_LIBRARY_ARCHITECTURE}/pkgconfig")
SET(INSTALL_PLUGINDIR_DEB "${INSTALL_LIBDIR_DEB}/libmariadb${CPACK_PACKAGE_VERSION_MAJOR}/plugin")
SET(INSTALL_INCLUDEDIR_DEB "include/mariadb")
SET(INSTALL_MANDIR_DEB "share/man")
SET(LIBMARIADB_STATIC_DEB "mariadb")
IF(INSTALL_LAYOUT MATCHES "DEB")
SET(INSTALL_PLUGINDIR_CLIENT ${INSTALL_PLUGINDIR_DEB})
ENDIF()
#
# Overwrite defaults
#
IF(INSTALL_LIBDIR)
SET(INSTALL_LIBDIR_${INSTALL_LAYOUT} ${INSTALL_LIBDIR})
ENDIF()
IF(INSTALL_PCDIR)
SET(INSTALL_PCDIR_${INSTALL_LAYOUT} ${INSTALL_PCDIR})
ENDIF()
IF(INSTALL_PLUGINDIR)
SET(INSTALL_PLUGINDIR_${INSTALL_LAYOUT} ${INSTALL_PLUGINDIR})
ENDIF()
# Extra INSTALL_PLUGINDIR_CLIENT that overrides any INSTALL_PLUGINDIR override
IF(INSTALL_PLUGINDIR_CLIENT)
SET(INSTALL_PLUGINDIR_${INSTALL_LAYOUT} ${INSTALL_PLUGINDIR_CLIENT})
ENDIF()
IF(INSTALL_INCLUDEDIR)
SET(INSTALL_INCLUDEDIR_${INSTALL_LAYOUT} ${INSTALL_INCLUDEDIR})
ENDIF()
IF(INSTALL_BINDIR)
SET(INSTALL_BINDIR_${INSTALL_LAYOUT} ${INSTALL_BINDIR})
ENDIF()
IF(INSTALL_MANDIR)
SET(INSTALL_MANDIR_${INSTALL_LAYOUT} ${INSTALL_MANDIR})
ENDIF()
IF(NOT INSTALL_PREFIXDIR)
SET(INSTALL_PREFIXDIR_${INSTALL_LAYOUT} ${libmariadb_prefix})
ELSE()
SET(INSTALL_PREFIXDIR_${INSTALL_LAYOUT} ${INSTALL_PREFIXDIR})
ENDIF()
IF(DEFINED INSTALL_SUFFIXDIR)
SET(INSTALL_SUFFIXDIR_${INSTALL_LAYOUT} ${INSTALL_SUFFIXDIR})
ENDIF()
FOREACH(dir "BIN" "LIB" "PC" "INCLUDE" "DOCS" "PLUGIN" "MAN")
SET(INSTALL_${dir}DIR ${INSTALL_${dir}DIR_${INSTALL_LAYOUT}})
MARK_AS_ADVANCED(INSTALL_${dir}DIR)
MESSAGE1(INSTALL_${dir}DIR "MariaDB Connector C: INSTALL_${dir}DIR=${INSTALL_${dir}DIR}")
ENDFOREACH()
SET(LIBMARIADB_STATIC_NAME ${LIBMARIADB_STATIC_${INSTALL_LAYOUT}})
MARK_AS_ADVANCED(LIBMARIADB_STATIC_NAME)
MESSAGE1(LIBMARIADB_STATIC_NAME "MariaDB Connector C: LIBMARIADB_STATIC_NAME ${LIBMARIADB_STATIC_NAME}")

View file

@ -0,0 +1,20 @@
#
# Copyright (C) 2013-2016 MariaDB Corporation AB
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the COPYING-CMAKE-SCRIPTS file.
#
# plugin installation
MACRO(INSTALL_PLUGIN name binary_dir)
INSTALL(TARGETS ${name} COMPONENT ClientPlugins DESTINATION ${INSTALL_PLUGINDIR})
IF(MSVC)
INSTALL(FILES $<TARGET_PDB_FILE:${name}> COMPONENT Debuginfo
DESTINATION symbols CONFIGURATIONS Debug RelWithDebInfo)
ENDIF()
IF(WIN32)
FILE(APPEND ${CC_BINARY_DIR}/win/packaging/plugin.conf "<File Id=\"${name}.dll\" Name=\"${name}.dll\" DiskId=\"1\" Source=\"${binary_dir}/${CMAKE_BUILD_TYPE}/${name}.dll\"/>\n")
FILE(APPEND ${CC_BINARY_DIR}/win/packaging/plugin.conf "<File Id=\"${name}.pdb\" Name=\"${name}.pdb\" DiskId=\"1\" Source=\"${binary_dir}/${CMAKE_BUILD_TYPE}/${name}.pdb\"/>\n")
ENDIF()
ENDMACRO()

View file

@ -0,0 +1,7 @@
#include <openssl/opensslv.h>
#include <stdio.h>
int main()
{
printf("%s", LIBRESSL_VERSION_TEXT);
}

View file

@ -0,0 +1,18 @@
#
# Copyright (C) 2013-2016 MariaDB Corporation AB
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the COPYING-CMAKE-SCRIPTS file.
#
# toolchain file for building a 32bit version on a 64bit host
# Usage:
# cmake -DCMAKE_TOOLCHAIN_FILE=linux_86.toolchain.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_SYSTEM_PROCESSOR "i686")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32" CACHE STRING "c++ flags")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32" CACHE STRING "c flags")

7
vendor/mariadb/cmake/misc.cmake vendored Normal file
View file

@ -0,0 +1,7 @@
FUNCTION(MESSAGE1 id out)
STRING(MD5 hash "${out}")
IF(NOT __msg1_${id} STREQUAL "${hash}")
MESSAGE(STATUS "${out}")
ENDIF()
SET(__msg1_${id} ${hash} CACHE INTERNAL "")
ENDFUNCTION()

103
vendor/mariadb/cmake/plugins.cmake vendored Normal file
View file

@ -0,0 +1,103 @@
#
# Copyright (C) 2013-2018 MariaDB Corporation AB
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the COPYING-CMAKE-SCRIPTS file.
#
# plugin configuration
include(${CC_SOURCE_DIR}/cmake/install_plugins.cmake)
include(${CC_SOURCE_DIR}/cmake/sign.cmake)
FUNCTION(REGISTER_PLUGIN)
SET(one_value_keywords TARGET DISABLED TYPE DEFAULT)
SET(multi_value_keywords CONFIGURATIONS SOURCES LIBRARIES INCLUDES COMPILE_OPTIONS)
cmake_parse_arguments(CC_PLUGIN
"${options}"
"${one_value_keywords}"
"${multi_value_keywords}"
${ARGN})
# overwrite default if it was specified with cmake option
string(TOUPPER ${CC_PLUGIN_TARGET} cc_plugin)
if(NOT "${CLIENT_PLUGIN_${cc_plugin}}" STREQUAL "")
SET(CC_PLUGIN_DEFAULT ${CLIENT_PLUGIN_${cc_plugin}})
endif()
# use uppercase
string(TOUPPER ${CC_PLUGIN_TARGET} target_name)
string(TOUPPER "${CC_PLUGIN_CONFIGURATIONS}" CC_PLUGIN_CONFIGURATIONS)
if(NOT ${PLUGIN_${target_name}} STREQUAL "")
string(TOUPPER ${PLUGIN_${target_name}} PLUGIN_${target_name})
set(CC_PLUGIN_DEFAULT ${PLUGIN_${target_name}})
endif()
# check if default value is valid
string(TOUPPER ${CC_PLUGIN_DEFAULT} CC_PLUGIN_DEFAULT)
list(FIND CC_PLUGIN_CONFIGURATIONS ${CC_PLUGIN_DEFAULT} configuration_found)
if(${configuration_found} EQUAL -1)
message(FATAL_ERROR "Invalid plugin type ${CC_PLUGIN_DEFAULT}. Allowed plugin types are ${CC_PLUGIN_CONFIGURATIONS}")
endif()
# check if plugin is disabled
string(TOUPPER "${CC_PLUGIN_DISABLED}" CC_PLUGIN_DISABLED)
if("${CC_PLUGIN_DISABLED}" STREQUAL "YES")
set(PLUGINS_DISABLED ${PLUGINS_DISABLED} ${CC_PLUGIN_TARGET} PARENT_SCOPE)
endif()
if(NOT ${CC_PLUGIN_DEFAULT} STREQUAL "OFF")
set(PLUGIN_${CC_PLUGIN_TARGET}_TYPE ${CC_PLUGIN_TYPE} PARENT_SCOPE)
if(${CC_PLUGIN_DEFAULT} MATCHES "DYNAMIC")
set(PLUGINS_DYNAMIC ${PLUGINS_DYNAMIC} ${CC_PLUGIN_TARGET} PARENT_SCOPE)
add_library(${CC_PLUGIN_TARGET} MODULE ${CC_PLUGIN_SOURCES})
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
if(NOT WITH_ASAN AND NOT WITH_TSAN AND NOT WITH_UBSAN AND NOT WITH_MSAN)
target_link_options(${CC_PLUGIN_TARGET} PRIVATE "-Wl,--no-undefined")
endif()
target_link_options(${CC_PLUGIN_TARGET} PRIVATE "-Wl,--dynamic-list=${CC_SOURCE_DIR}/plugins/dynamic_plugin_exports.txt")
elseif(WIN32)
set(target ${CC_PLUGIN_TARGET})
set(FILE_TYPE "VFT_DLL")
set(FILE_DESCRIPTION "MariaDB client plugin")
set(FILE_VERSION ${CPACK_PACKAGE_VERSION})
set(ORIGINAL_FILE_NAME "${target}.dll")
configure_file(${CC_SOURCE_DIR}/win/resource.rc.in
${CC_BINARY_DIR}/win/${target}.rc
@ONLY)
target_sources(${CC_PLUGIN_TARGET} PRIVATE
${CC_BINARY_DIR}/win/${target}.rc ${CC_SOURCE_DIR}/plugins/plugin.def)
endif()
target_link_libraries(${CC_PLUGIN_TARGET} ${CC_PLUGIN_LIBRARIES})
set_target_properties(${CC_PLUGIN_TARGET} PROPERTIES PREFIX "")
set_target_properties(${CC_PLUGIN_TARGET}
PROPERTIES COMPILE_FLAGS
"-DPLUGIN_DYNAMIC=1 ${CC_PLUGIN_COMPILE_OPTIONS}")
if (NOT "${CC_PLUGIN_INCLUDES}" STREQUAL "")
target_include_directories(${CC_PLUGIN_TARGET} PRIVATE ${CC_PLUGIN_INCLUDES})
endif()
if (${CC_TARGET_COMPILE_OPTIONS})
target_compile_options(${CC_PLUGIN_TARGET} ${CC_TARGET_COMPILE_OPTIONS})
endif()
if(WIN32)
SIGN_TARGET(${target})
endif()
INSTALL_PLUGIN(${CC_PLUGIN_TARGET} ${CMAKE_CURRENT_BINARY_DIR})
endif()
if(${CC_PLUGIN_DEFAULT} MATCHES "STATIC")
set(PLUGINS_STATIC ${PLUGINS_STATIC} ${CC_PLUGIN_TARGET} PARENT_SCOPE)
set(LIBMARIADB_PLUGIN_CFLAGS ${LIBMARIADB_PLUGIN_CFLAGS} ${CC_PLUGIN_COMPILE_OPTIONS} PARENT_SCOPE)
set(LIBMARIADB_PLUGIN_INCLUDES ${LIBMARIADB_PLUGIN_INCLUDES} ${CC_PLUGIN_INCLUDES} PARENT_SCOPE)
set(LIBMARIADB_PLUGIN_SOURCES ${LIBMARIADB_PLUGIN_SOURCES} ${CC_PLUGIN_SOURCES} PARENT_SCOPE)
set(LIBMARIADB_PLUGIN_LIBS ${LIBMARIADB_PLUGIN_LIBS} ${CC_PLUGIN_LIBRARIES} PARENT_SCOPE)
endif()
else()
set(PLUGINS_OFF ${PLUGINS_OFF} ${CC_PLUGIN_TARGET})
endif()
endfunction()

20
vendor/mariadb/cmake/sign.cmake vendored Normal file
View file

@ -0,0 +1,20 @@
#
# Copyright (C) 2013-2016 MariaDB Corporation AB
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the COPYING-CMAKE-SCRIPTS file.
#
IF(COMMAND SIGN_TARGET)
# Do not override server's SIGN_TARGET macro
RETURN()
ENDIF()
MACRO(SIGN_TARGET target)
IF(WITH_SIGNCODE)
IF(WIN32)
SET(target_file $<TARGET_FILE:${target}>)
ADD_CUSTOM_COMMAND(TARGET ${target} COMMAND signtool ARGS sign ${SIGN_OPTIONS} ${target_file})
ENDIF()
ENDIF()
ENDMACRO()

35
vendor/mariadb/cmake/symlink.cmake vendored Normal file
View file

@ -0,0 +1,35 @@
#
# Copyright (C) 2013-2016 MariaDB Corporation AB
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the COPYING-CMAKE-SCRIPTS file.
#
MACRO(create_symlink symlink_name target install_path)
# According to cmake documentation symlinks work on unix systems only
IF(UNIX)
# Get target components
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${symlink_name}
COMMAND ${CMAKE_COMMAND} ARGS -E remove -f ${symlink_name}
COMMAND ${CMAKE_COMMAND} ARGS -E create_symlink $<TARGET_FILE_NAME:${target}> ${symlink_name}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS ${target}
)
ADD_CUSTOM_TARGET(SYM_${symlink_name}
ALL
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${symlink_name})
SET_TARGET_PROPERTIES(SYM_${symlink_name} PROPERTIES CLEAN_DIRECT_OUTPUT 1)
IF(CMAKE_GENERATOR MATCHES "Xcode")
# For Xcode, replace project config with install config
STRING(REPLACE "${CMAKE_CFG_INTDIR}"
"\${CMAKE_INSTALL_CONFIG_NAME}" output ${CMAKE_CURRENT_BINARY_DIR}/${symlink_name})
ENDIF()
# presumably this will be used for libmysql*.so symlinks
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${symlink_name} DESTINATION ${install_path}
COMPONENT Development)
ENDIF()
ENDMACRO()

44
vendor/mariadb/cmake/version_info.cmake vendored Normal file
View file

@ -0,0 +1,44 @@
#
# Copyright (C) 2013-2016 MariaDB Corporation AB
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the COPYING-CMAKE-SCRIPTS file.
#
FUNCTION(GET_FILE_VERSION FILE_NAME FILE_VERSION)
# if we build from a git repository, we calculate the file version:
# Patch number is number of commits for given file
IF(GIT_EXECUTABLE AND EXISTS ${CC_SOURCE_DIR}/.git)
EXECUTE_PROCESS(COMMAND ${GIT_EXECUTABLE} --git-dir=${CC_SOURCE_DIR}/.git --work-tree=${CC_SOURCE_DIR} rev-list HEAD --count -- ${FILE_NAME}
OUTPUT_VARIABLE FV)
STRING(REPLACE "\n" "" FV ${FV})
SET(${FILE_VERSION} ${FV} PARENT_SCOPE)
ELSE()
SET(${FILE_VERSION} 0)
ENDIF()
ENDFUNCTION()
MACRO(SET_VERSION_INFO)
SET(FILE_VERSION "0")
FOREACH(PROPERTY ${ARGN})
IF(${PROPERTY} MATCHES "TARGET:")
STRING(REGEX REPLACE "^[TARGET:\\s]" "" TARGET ${PROPERTY})
ELSEIF(${PROPERTY} MATCHES "FILE_TYPE:")
STRING(REGEX REPLACE "^[FILE_TYPE:\\s]" "" FILE_TYPE ${PROPERTY})
ELSEIF(${PROPERTY} MATCHES "ORIGINAL_FILE_NAME:")
STRING(REGEX REPLACE "^[ORIGINAL_FILE_NAME:\\s]" "" ORIGINAL_FILE_NAME ${PROPERTY})
ELSEIF(${PROPERTY} MATCHES "SOURCE_FILE:")
STRING(REGEX REPLACE "^[SOURCE_FILE:\\s]" "" SOURCE ${PROPERTY})
GET_FILE_VERSION(${SOURCE} FILE_VERSION)
ELSEIF(${PROPERTY} MATCHES "FILE_DESCRIPTION:")
STRING(REPLACE "FILE_DESCRIPTION:" "" FILE_DESCRIPTION ${PROPERTY})
ENDIF()
ENDFOREACH()
CONFIGURE_FILE(${CC_SOURCE_DIR}/win/resource.rc.in
${CC_BINARY_DIR}/win/${TARGET}.rc)
SET(${TARGET}_RC ${CC_BINARY_DIR}/win/${TARGET}.rc)
ENDMACRO()

View file

@ -0,0 +1,152 @@
cmake_minimum_required(VERSION 2.4.4...3.15.0)
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
project(zlib C)
set(VERSION "1.3.1")
option(ZLIB_BUILD_EXAMPLES "Enable Zlib Examples" ON)
set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers")
set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages")
set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")
include(CheckTypeSize)
include(CheckFunctionExists)
include(CheckIncludeFile)
include(CheckCSourceCompiles)
enable_testing()
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
check_include_file(stdint.h HAVE_STDINT_H)
check_include_file(stddef.h HAVE_STDDEF_H)
#
# Check to see if we have large file support
#
set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1)
# We add these other definitions here because CheckTypeSize.cmake
# in CMake 2.4.x does not automatically do so and we want
# compatibility with CMake 2.4.x.
if(HAVE_SYS_TYPES_H)
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H)
endif()
if(HAVE_STDINT_H)
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H)
endif()
if(HAVE_STDDEF_H)
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H)
endif()
check_type_size(off64_t OFF64_T)
if(HAVE_OFF64_T)
add_definitions(-D_LARGEFILE64_SOURCE=1)
endif()
set(CMAKE_REQUIRED_DEFINITIONS) # clear variable
#
# Check for fseeko
#
check_function_exists(fseeko HAVE_FSEEKO)
if(NOT HAVE_FSEEKO)
add_definitions(-DNO_FSEEKO)
endif()
#
# Check for unistd.h
#
check_include_file(unistd.h Z_HAVE_UNISTD_H)
if(MSVC)
set(CMAKE_DEBUG_POSTFIX "d")
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
endif()
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
# If we're doing an out of source build and the user has a zconf.h
# in their source tree...
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h)
message(STATUS "Renaming")
message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h")
message(STATUS "to 'zconf.h.included' because this file is included with zlib")
message(STATUS "but CMake generates it automatically in the build directory.")
file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included)
endif()
endif()
set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc)
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein
${ZLIB_PC} @ONLY)
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein
${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY)
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR})
#============================================================================
# zlib
#============================================================================
set(ZLIB_PUBLIC_HDRS
${CMAKE_CURRENT_BINARY_DIR}/zconf.h
zlib.h
)
set(ZLIB_PRIVATE_HDRS
crc32.h
deflate.h
gzguts.h
inffast.h
inffixed.h
inflate.h
inftrees.h
trees.h
zutil.h
)
set(ZLIB_SRCS
adler32.c
compress.c
crc32.c
deflate.c
gzclose.c
gzlib.c
gzread.c
gzwrite.c
inflate.c
infback.c
inftrees.c
inffast.c
trees.c
uncompr.c
zutil.c
)
if(NOT MINGW)
set(ZLIB_DLL_SRCS
win32/zlib1.rc # If present will override custom build rule below.
)
endif()
# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents)
string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*"
"\\1" ZLIB_FULL_VERSION ${_zlib_h_contents})
if(MINGW)
# This gets us DLL resource information when compiling on MinGW.
if(NOT CMAKE_RC_COMPILER)
set(CMAKE_RC_COMPILER windres.exe)
endif()
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
COMMAND ${CMAKE_RC_COMPILER}
-D GCC_WINDRES
-I ${CMAKE_CURRENT_SOURCE_DIR}
-I ${CMAKE_CURRENT_BINARY_DIR}
-o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
-i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc)
set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj)
endif(MINGW)
add_library(zlib STATIC ${ZLIB_SRCS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})

1618
vendor/mariadb/external/zlib/ChangeLog vendored Normal file

File diff suppressed because it is too large Load diff

367
vendor/mariadb/external/zlib/FAQ vendored Normal file
View file

@ -0,0 +1,367 @@
Frequently Asked Questions about zlib
If your question is not there, please check the zlib home page
http://zlib.net/ which may have more recent information.
The latest zlib FAQ is at http://zlib.net/zlib_faq.html
1. Is zlib Y2K-compliant?
Yes. zlib doesn't handle dates.
2. Where can I get a Windows DLL version?
The zlib sources can be compiled without change to produce a DLL. See the
file win32/DLL_FAQ.txt in the zlib distribution.
3. Where can I get a Visual Basic interface to zlib?
See
* http://marknelson.us/1997/01/01/zlib-engine/
* win32/DLL_FAQ.txt in the zlib distribution
4. compress() returns Z_BUF_ERROR.
Make sure that before the call of compress(), the length of the compressed
buffer is equal to the available size of the compressed buffer and not
zero. For Visual Basic, check that this parameter is passed by reference
("as any"), not by value ("as long").
5. deflate() or inflate() returns Z_BUF_ERROR.
Before making the call, make sure that avail_in and avail_out are not zero.
When setting the parameter flush equal to Z_FINISH, also make sure that
avail_out is big enough to allow processing all pending input. Note that a
Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be
made with more input or output space. A Z_BUF_ERROR may in fact be
unavoidable depending on how the functions are used, since it is not
possible to tell whether or not there is more output pending when
strm.avail_out returns with zero. See http://zlib.net/zlib_how.html for a
heavily annotated example.
6. Where's the zlib documentation (man pages, etc.)?
It's in zlib.h . Examples of zlib usage are in the files test/example.c
and test/minigzip.c, with more in examples/ .
7. Why don't you use GNU autoconf or libtool or ...?
Because we would like to keep zlib as a very small and simple package.
zlib is rather portable and doesn't need much configuration.
8. I found a bug in zlib.
Most of the time, such problems are due to an incorrect usage of zlib.
Please try to reproduce the problem with a small program and send the
corresponding source to us at zlib@gzip.org . Do not send multi-megabyte
data files without prior agreement.
9. Why do I get "undefined reference to gzputc"?
If "make test" produces something like
example.o(.text+0x154): undefined reference to `gzputc'
check that you don't have old files libz.* in /usr/lib, /usr/local/lib or
/usr/X11R6/lib. Remove any old versions, then do "make install".
10. I need a Delphi interface to zlib.
See the contrib/delphi directory in the zlib distribution.
11. Can zlib handle .zip archives?
Not by itself, no. See the directory contrib/minizip in the zlib
distribution.
12. Can zlib handle .Z files?
No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt
the code of uncompress on your own.
13. How can I make a Unix shared library?
By default a shared (and a static) library is built for Unix. So:
make distclean
./configure
make
14. How do I install a shared zlib library on Unix?
After the above, then:
make install
However, many flavors of Unix come with a shared zlib already installed.
Before going to the trouble of compiling a shared version of zlib and
trying to install it, you may want to check if it's already there! If you
can #include <zlib.h>, it's there. The -lz option will probably link to
it. You can check the version at the top of zlib.h or with the
ZLIB_VERSION symbol defined in zlib.h .
15. I have a question about OttoPDF.
We are not the authors of OttoPDF. The real author is on the OttoPDF web
site: Joel Hainley, jhainley@myndkryme.com.
16. Can zlib decode Flate data in an Adobe PDF file?
Yes. See http://www.pdflib.com/ . To modify PDF forms, see
http://sourceforge.net/projects/acroformtool/ .
17. Why am I getting this "register_frame_info not found" error on Solaris?
After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib
generates an error such as:
ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so:
symbol __register_frame_info: referenced symbol not found
The symbol __register_frame_info is not part of zlib, it is generated by
the C compiler (cc or gcc). You must recompile applications using zlib
which have this problem. This problem is specific to Solaris. See
http://www.sunfreeware.com for Solaris versions of zlib and applications
using zlib.
18. Why does gzip give an error on a file I make with compress/deflate?
The compress and deflate functions produce data in the zlib format, which
is different and incompatible with the gzip format. The gz* functions in
zlib on the other hand use the gzip format. Both the zlib and gzip formats
use the same compressed data format internally, but have different headers
and trailers around the compressed data.
19. Ok, so why are there two different formats?
The gzip format was designed to retain the directory information about a
single file, such as the name and last modification date. The zlib format
on the other hand was designed for in-memory and communication channel
applications, and has a much more compact header and trailer and uses a
faster integrity check than gzip.
20. Well that's nice, but how do I make a gzip file in memory?
You can request that deflate write the gzip format instead of the zlib
format using deflateInit2(). You can also request that inflate decode the
gzip format using inflateInit2(). Read zlib.h for more details.
21. Is zlib thread-safe?
Yes. However any library routines that zlib uses and any application-
provided memory allocation routines must also be thread-safe. zlib's gz*
functions use stdio library routines, and most of zlib's functions use the
library memory allocation routines by default. zlib's *Init* functions
allow for the application to provide custom memory allocation routines.
Of course, you should only operate on any given zlib or gzip stream from a
single thread at a time.
22. Can I use zlib in my commercial application?
Yes. Please read the license in zlib.h.
23. Is zlib under the GNU license?
No. Please read the license in zlib.h.
24. The license says that altered source versions must be "plainly marked". So
what exactly do I need to do to meet that requirement?
You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In
particular, the final version number needs to be changed to "f", and an
identification string should be appended to ZLIB_VERSION. Version numbers
x.x.x.f are reserved for modifications to zlib by others than the zlib
maintainers. For example, if the version of the base zlib you are altering
is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and
ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also
update the version strings in deflate.c and inftrees.c.
For altered source distributions, you should also note the origin and
nature of the changes in zlib.h, as well as in ChangeLog and README, along
with the dates of the alterations. The origin should include at least your
name (or your company's name), and an email address to contact for help or
issues with the library.
Note that distributing a compiled zlib library along with zlib.h and
zconf.h is also a source distribution, and so you should change
ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes
in zlib.h as you would for a full source distribution.
25. Will zlib work on a big-endian or little-endian architecture, and can I
exchange compressed data between them?
Yes and yes.
26. Will zlib work on a 64-bit machine?
Yes. It has been tested on 64-bit machines, and has no dependence on any
data types being limited to 32-bits in length. If you have any
difficulties, please provide a complete problem report to zlib@gzip.org
27. Will zlib decompress data from the PKWare Data Compression Library?
No. The PKWare DCL uses a completely different compressed data format than
does PKZIP and zlib. However, you can look in zlib's contrib/blast
directory for a possible solution to your problem.
28. Can I access data randomly in a compressed stream?
No, not without some preparation. If when compressing you periodically use
Z_FULL_FLUSH, carefully write all the pending data at those points, and
keep an index of those locations, then you can start decompression at those
points. You have to be careful to not use Z_FULL_FLUSH too often, since it
can significantly degrade compression. Alternatively, you can scan a
deflate stream once to generate an index, and then use that index for
random access. See examples/zran.c .
29. Does zlib work on MVS, OS/390, CICS, etc.?
It has in the past, but we have not heard of any recent evidence. There
were working ports of zlib 1.1.4 to MVS, but those links no longer work.
If you know of recent, successful applications of zlib on these operating
systems, please let us know. Thanks.
30. Is there some simpler, easier to read version of inflate I can look at to
understand the deflate format?
First off, you should read RFC 1951. Second, yes. Look in zlib's
contrib/puff directory.
31. Does zlib infringe on any patents?
As far as we know, no. In fact, that was originally the whole point behind
zlib. Look here for some more information:
http://www.gzip.org/#faq11
32. Can zlib work with greater than 4 GB of data?
Yes. inflate() and deflate() will process any amount of data correctly.
Each call of inflate() or deflate() is limited to input and output chunks
of the maximum value that can be stored in the compiler's "unsigned int"
type, but there is no limit to the number of chunks. Note however that the
strm.total_in and strm_total_out counters may be limited to 4 GB. These
counters are provided as a convenience and are not used internally by
inflate() or deflate(). The application can easily set up its own counters
updated after each call of inflate() or deflate() to count beyond 4 GB.
compress() and uncompress() may be limited to 4 GB, since they operate in a
single call. gzseek() and gztell() may be limited to 4 GB depending on how
zlib is compiled. See the zlibCompileFlags() function in zlib.h.
The word "may" appears several times above since there is a 4 GB limit only
if the compiler's "long" type is 32 bits. If the compiler's "long" type is
64 bits, then the limit is 16 exabytes.
33. Does zlib have any security vulnerabilities?
The only one that we are aware of is potentially in gzprintf(). If zlib is
compiled to use sprintf() or vsprintf(), then there is no protection
against a buffer overflow of an 8K string space (or other value as set by
gzbuffer()), other than the caller of gzprintf() assuring that the output
will not exceed 8K. On the other hand, if zlib is compiled to use
snprintf() or vsnprintf(), which should normally be the case, then there is
no vulnerability. The ./configure script will display warnings if an
insecure variation of sprintf() will be used by gzprintf(). Also the
zlibCompileFlags() function will return information on what variant of
sprintf() is used by gzprintf().
If you don't have snprintf() or vsnprintf() and would like one, you can
find a portable implementation here:
http://www.ijs.si/software/snprintf/
Note that you should be using the most recent version of zlib. Versions
1.1.3 and before were subject to a double-free vulnerability, and versions
1.2.1 and 1.2.2 were subject to an access exception when decompressing
invalid compressed data.
34. Is there a Java version of zlib?
Probably what you want is to use zlib in Java. zlib is already included
as part of the Java SDK in the java.util.zip package. If you really want
a version of zlib written in the Java language, look on the zlib home
page for links: http://zlib.net/ .
35. I get this or that compiler or source-code scanner warning when I crank it
up to maximally-pedantic. Can't you guys write proper code?
Many years ago, we gave up attempting to avoid warnings on every compiler
in the universe. It just got to be a waste of time, and some compilers
were downright silly as well as contradicted each other. So now, we simply
make sure that the code always works.
36. Valgrind (or some similar memory access checker) says that deflate is
performing a conditional jump that depends on an uninitialized value.
Isn't that a bug?
No. That is intentional for performance reasons, and the output of deflate
is not affected. This only started showing up recently since zlib 1.2.x
uses malloc() by default for allocations, whereas earlier versions used
calloc(), which zeros out the allocated memory. Even though the code was
correct, versions 1.2.4 and later was changed to not stimulate these
checkers.
37. Will zlib read the (insert any ancient or arcane format here) compressed
data format?
Probably not. Look in the comp.compression FAQ for pointers to various
formats and associated software.
38. How can I encrypt/decrypt zip files with zlib?
zlib doesn't support encryption. The original PKZIP encryption is very
weak and can be broken with freely available programs. To get strong
encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib
compression. For PKZIP compatible "encryption", look at
http://www.info-zip.org/
39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
"gzip" is the gzip format, and "deflate" is the zlib format. They should
probably have called the second one "zlib" instead to avoid confusion with
the raw deflate compressed data format. While the HTTP 1.1 RFC 2616
correctly points to the zlib specification in RFC 1950 for the "deflate"
transfer encoding, there have been reports of servers and browsers that
incorrectly produce or expect raw deflate data per the deflate
specification in RFC 1951, most notably Microsoft. So even though the
"deflate" transfer encoding using the zlib format would be the more
efficient approach (and in fact exactly what the zlib format was designed
for), using the "gzip" transfer encoding is probably more reliable due to
an unfortunate choice of name on the part of the HTTP 1.1 authors.
Bottom line: use the gzip format for HTTP 1.1 encoding.
40. Does zlib support the new "Deflate64" format introduced by PKWare?
No. PKWare has apparently decided to keep that format proprietary, since
they have not documented it as they have previous compression formats. In
any case, the compression improvements are so modest compared to other more
modern approaches, that it's not worth the effort to implement.
41. I'm having a problem with the zip functions in zlib, can you help?
There are no zip functions in zlib. You are probably using minizip by
Giles Vollant, which is found in the contrib directory of zlib. It is not
part of zlib. In fact none of the stuff in contrib is part of zlib. The
files in there are not supported by the zlib authors. You need to contact
the authors of the respective contribution for help.
42. The match.asm code in contrib is under the GNU General Public License.
Since it's part of zlib, doesn't that mean that all of zlib falls under the
GNU GPL?
No. The files in contrib are not part of zlib. They were contributed by
other authors and are provided as a convenience to the user within the zlib
distribution. Each item in contrib has its own license.
43. Is zlib subject to export controls? What is its ECCN?
zlib is not subject to export controls, and so is classified as EAR99.
44. Can you please sign these lengthy legal documents and fax them back to us
so that we can use your software in our product?
No. Go away. Shoo.

68
vendor/mariadb/external/zlib/INDEX vendored Normal file
View file

@ -0,0 +1,68 @@
CMakeLists.txt cmake build file
ChangeLog history of changes
FAQ Frequently Asked Questions about zlib
INDEX this file
Makefile dummy Makefile that tells you to ./configure
Makefile.in template for Unix Makefile
README guess what
configure configure script for Unix
make_vms.com makefile for VMS
test/example.c zlib usages examples for build testing
test/minigzip.c minimal gzip-like functionality for build testing
test/infcover.c inf*.c code coverage for build coverage testing
treebuild.xml XML description of source file dependencies
zconf.h.cmakein zconf.h template for cmake
zconf.h.in zconf.h template for configure
zlib.3 Man page for zlib
zlib.3.pdf Man page in PDF format
zlib.map Linux symbol information
zlib.pc.in Template for pkg-config descriptor
zlib.pc.cmakein zlib.pc template for cmake
zlib2ansi perl script to convert source files for C++ compilation
amiga/ makefiles for Amiga SAS C
as400/ makefiles for AS/400
doc/ documentation for formats and algorithms
msdos/ makefiles for MSDOS
nintendods/ makefile for Nintendo DS
old/ makefiles for various architectures and zlib documentation
files that have not yet been updated for zlib 1.2.x
qnx/ makefiles for QNX
watcom/ makefiles for OpenWatcom
win32/ makefiles for Windows
zlib public header files (required for library use):
zconf.h
zlib.h
private source files used to build the zlib library:
adler32.c
compress.c
crc32.c
crc32.h
deflate.c
deflate.h
gzclose.c
gzguts.h
gzlib.c
gzread.c
gzwrite.c
infback.c
inffast.c
inffast.h
inffixed.h
inflate.c
inflate.h
inftrees.c
inftrees.h
trees.c
trees.h
uncompr.c
zutil.c
zutil.h
source files for sample programs
See examples/README.examples
unsupported contributions by third parties
See contrib/README.contrib

Some files were not shown because too many files have changed in this diff Show more