JSO compiler; packer; update CDB to 0.80; assets now packed into binary

This commit is contained in:
John Alanbrook 2023-09-18 12:36:07 +00:00
parent 97483d4ce5
commit c9c05d931d
68 changed files with 1306 additions and 347 deletions

View file

@ -1,4 +1,4 @@
MAKEFLAGS = --jobs=8
MAKEFLAGS = --jobs=4
UNAME != uname
MAKEDIR != pwd
@ -94,7 +94,9 @@ else
ifeq ($(UNAME), Darwin)
CFLAGS += -x objective-c
LDFLAGS += -framework Cocoa -framework QuartzCore -framework OpenGL -framework AudioToolbox
LDFLAGS += -framework Cocoa -framework QuartzCore -framework AudioToolbox
# LDFLAGS += -framework Metal -framework MetalKit
LDFLAGS += -framework OpenGL
PLAT = osx-$(ARCH)$(INFO)
endif
endif
@ -110,7 +112,7 @@ OBJS := $(addprefix $(BIN)/obj/, $(OBJS))
engineincs != find source/engine -maxdepth 1 -type d
includeflag != find source -type d -name include
includeflag += $(engineincs) source/engine/thirdparty/Nuklear source/engine/thirdparty/tinycdb-0.78 source/shaders
includeflag += $(engineincs) source/engine/thirdparty/Nuklear source/engine/thirdparty/tinycdb source/shaders
includeflag := $(addprefix -I, $(includeflag))
WARNING_FLAGS = -Wno-incompatible-function-pointer-types -Wno-incompatible-pointer-types -Wno-unused-function -Wno-unused-const-variable
@ -125,7 +127,6 @@ LDLIBS := $(addprefix -l, $(LDLIBS))
DEPENDS = $(OBJS:.o=.d)
-include $(DEPENDS)
SCRIPTS = $(shell ls source/scripts/*.js)
MYTAG = $(VER)_$(PTYPE)_$(INFO)
@ -133,32 +134,35 @@ DIST = yugine-$(PLAT)-$(COM)$(ZIP)
DISTDIR = ./dist
.DEFAULT_GOAL := all
all: $(DISTDIR)/$(DIST)
all: $(BIN)/$(NAME)
DESTDIR ?= ~/.bin
CDB = source/engine/thirdparty/tinycdb
SHADERS = $(shell ls source/shaders/*.sglsl)
SHADERS := $(patsubst %.sglsl, %.sglsl.h, $(SHADERS))
install: $(DISTDIR)/$(DIST)
@echo Unpacking $(DIST) in $(DESTDIR)
@$(UNZIP)
install: $(BIN)/$(NAME)
cp $(BIN)/$(NAME) $(DESTDIR)
$(BIN)/$(NAME): $(BIN)/libengine.a $(BIN)/libquickjs.a
$(BIN)/$(NAME): $(BIN)/libengine.a $(BIN)/libquickjs.a $(BIN)/libcdb.a
@echo Linking $(NAME)
$(LD) $^ $(LDFLAGS) -L$(BIN) $(LDLIBS) -o $@
@echo Finished build
$(DISTDIR)/$(DIST): $(BIN)/$(NAME) $(SCRIPTS) assets/*
$(DISTDIR)/$(DIST): $(BIN)/$(NAME)
@echo Creating distribution $(DIST)
@mkdir -p $(DISTDIR)
@cp -rf assets/* $(BIN)
@cp -rf source/scripts $(BIN)
@$(PKGCMD)
$(BIN)/libengine.a: $(OBJS)
@$(AR) rcs $@ $(OBJS)
$(BIN)/libcdb.a:
make -C $(CDB) libcdb.a
cp $(CDB)/libcdb.a $(BIN)
$(BIN)/libquickjs.a:
make -C quickjs clean
make -C quickjs OPT=$(OPT) HOST_CC=$(CC) libquickjs.a libquickjs.lto.a CC=$(CC)
@ -177,14 +181,36 @@ shaders: $(SHADERS)
@echo Creating shader $^
@./sokol-shdc --ifdef -i $^ --slang=glsl330:hlsl5:metal_macos -o $@
cdb: tools/cdb.c $(BIN)/libcdb.a
$(CC) $^ -I$(CDB) -o cdb
source/engine/core.cdb.h: core.cdb
xxd -i $< > $@
SCRIPTS := $(shell ls scripts/*.js)
SCRIPT_O := $(addsuffix o, $(SCRIPTS))
CORE != (ls icons/* fonts/*)
CORE := $(CORE) $(SCRIPTS)
core.cdb: packer $(CORE)
./packer $(CORE)
chmod 644 out.cdb
mv out.cdb core.cdb
packer: tools/packer.c $(BIN)/libcdb.a
cc $^ -Isource/engine/thirdparty/tinycdb -o packer
jso: tools/jso.c quickjs/libquickjs.a
cc tools/jso.c -lquickjs -Lquickjs -Iquickjs -o jso
%.jso: %.js jso
@echo Making $@ from $<
./jso $< > $@
clean:
@echo Cleaning project
@rm -rf bin/*
@rm -f *.gz
@rm -f source/shaders/*.sglsl.h
@rm -f source/shaders/*.metal
@rm -rf dist/*
@rm TAGS
@rm -rf bin/* dist/*
@rm -f shaders/*.sglsl.h shaders/*.metal core.cdb jso cdb packer TAGS
TAGINC != find . -name "*.[chj]"
tags: $(TAGINC)

View file

Before

Width:  |  Height:  |  Size: 298 B

After

Width:  |  Height:  |  Size: 298 B

View file

Before

Width:  |  Height:  |  Size: 187 B

After

Width:  |  Height:  |  Size: 187 B

View file

Before

Width:  |  Height:  |  Size: 225 B

After

Width:  |  Height:  |  Size: 225 B

View file

Before

Width:  |  Height:  |  Size: 293 B

After

Width:  |  Height:  |  Size: 293 B

View file

Before

Width:  |  Height:  |  Size: 157 B

After

Width:  |  Height:  |  Size: 157 B

View file

Before

Width:  |  Height:  |  Size: 197 B

After

Width:  |  Height:  |  Size: 197 B

View file

Before

Width:  |  Height:  |  Size: 226 B

After

Width:  |  Height:  |  Size: 226 B

View file

Before

Width:  |  Height:  |  Size: 108 B

After

Width:  |  Height:  |  Size: 108 B

View file

Before

Width:  |  Height:  |  Size: 339 B

After

Width:  |  Height:  |  Size: 339 B

View file

Before

Width:  |  Height:  |  Size: 234 B

After

Width:  |  Height:  |  Size: 234 B

View file

Before

Width:  |  Height:  |  Size: 187 B

After

Width:  |  Height:  |  Size: 187 B

View file

Before

Width:  |  Height:  |  Size: 224 B

After

Width:  |  Height:  |  Size: 224 B

View file

Before

Width:  |  Height:  |  Size: 206 B

After

Width:  |  Height:  |  Size: 206 B

View file

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 304 B

View file

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View file

@ -14,9 +14,9 @@ load("scripts/std.js");
function initialize()
{
if (!Game.edit)
run("scripts/play.js");
load("scripts/play.js");
else
run("scripts/editor.js");
load("scripts/editor.js");
}
function run(file)
@ -629,3 +629,5 @@ Game.view_camera(Primum.spawn(ur.camera2d));
Window.name = "Primum Machinam (V0.1)";
Window.width = 1280;
Window.height = 720;
Log.warn("AMDE IT");

View file

@ -646,6 +646,11 @@ static inline HMM_Vec4 HMM_SubV4(HMM_Vec4 Left, HMM_Vec4 Right) {
return Result;
}
static inline HMM_Vec2 HMM_ScaleV2(HMM_Vec2 v, double s)
{
return HMM_V2(v.X*s, v.Y*s);
}
static inline HMM_Vec2 HMM_MulV2(HMM_Vec2 Left, HMM_Vec2 Right) {
HMM_Vec2 Result;

View file

@ -1099,6 +1099,14 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
case 135:
ret = float2js(cam_zoom());
break;
case 136:
ret = v22js(world2screen(js2hmmv2(argv[1])));
break;
case 137:
ret = v22js(screen2world(js2hmmv2(argv[1])));
break;
}
if (str)

View file

@ -382,9 +382,6 @@ void call_input_down(int *key) {
/* This is called once every frame - or more if we want it more! */
void input_poll(double wait) {
mouse_delta = cpvzero;
mousewheel = cpvzero;
for (int i = 0; i < arrlen(downkeys); i++)
call_input_down(&downkeys[i]);
}

View file

@ -15,6 +15,10 @@
#include "stb_ds.h"
#include "resources.h"
#include "yugine.h"
#include "sokol/sokol_app.h"
#define SOKOL_GLUE_IMPL
#include "sokol/sokol_glue.h"
#include "crt.sglsl.h"
#include "box.sglsl.h"
@ -209,6 +213,8 @@ void render_init() {
mainwin.height = sapp_height();
sg_setup(&(sg_desc){
.context = sapp_sgcontext(),
.mtl_force_managed_storage_mode = 1,
.logger = {
.func = sg_logging,
.user_data = NULL,
@ -372,9 +378,23 @@ cpVect cam_pos() {
static float zoom = 1.f;
float cam_zoom() { return zoom; }
void add_zoom(float val) { zoom = val; }
HMM_Vec2 world2screen(HMM_Vec2 pos)
{
pos = HMM_SubV2(pos, HMM_V2(cam_pos().x, cam_pos().y));
pos = HMM_ScaleV2(pos, 1.0/zoom);
pos = HMM_AddV2(pos, HMM_V2(mainwin.width/2.0, mainwin.height/2.0));
return pos;
}
HMM_Vec2 screen2world(HMM_Vec2 pos)
{
pos = HMM_AddV2(pos, HMM_V2(mainwin.width/2.0, mainwin.height/2.0));
pos = HMM_MulV2(pos, HMM_V2(zoom,zoom));
return HMM_AddV2(pos, HMM_V2(cam_pos().x, cam_pos().y));
}
HMM_Mat4 projection = {0.f};
HMM_Mat4 hudproj = {0.f};

View file

@ -9,6 +9,7 @@
#define SOKOL_GLCORE33
#define SOKOL_WIN32_FORCE_MAIN
#elif __APPLE__
// #define SOKOL_METAL
#define SOKOL_GLCORE33
#endif
@ -77,6 +78,8 @@ void set_cam_body(cpBody *body);
cpVect cam_pos();
float cam_zoom();
void add_zoom(float val);
HMM_Vec2 world2screen(HMM_Vec2 pos);
HMM_Vec2 screen2world(HMM_Vec2 pos);
sg_shader sg_compile_shader(const char *v, const char *f, sg_shader_desc *d);

View file

@ -22,6 +22,8 @@
#include "stb_ds.h"
#include "core.cdb.h"
char *DATA_PATH = NULL;
char *PREF_PATH = NULL;
@ -36,8 +38,8 @@ char pathbuf[MAXPATH + 1];
const char *DB_NAME = "test.db";
static struct cdb corecdb;
static struct cdb game_cdb;
static int loaded_cdb = 0;
void resources_init() {
DATA_PATH = malloc(MAXPATH);
@ -47,10 +49,9 @@ void resources_init() {
if (!PREF_PATH)
PREF_PATH = strdup("./tmp/");
int fd;
fd = open("test.cdb", O_RDONLY);
int fd = open("test.cdb", O_RDONLY);
cdb_init(&game_cdb, fd);
loaded_cdb = 1;
cdb_initf(&corecdb, core_cdb, core_cdb_len);
}
char *get_filename_from_path(char *path, int extension) {
@ -86,6 +87,21 @@ FILE *res_open(char *path, const char *tag) {
return f;
}
char *seprint(char *fmt, ...)
{
va_list args;
va_start (args, fmt);
char test[128];
int len = vsnprintf(test, 128, fmt, args);
if (len > 128) {
char test = malloc(len+1);
vsnprintf(test, len+1, fmt, args);
return strdup(test);
}
return strdup(test);
}
static char *ext_paths = NULL;
#ifndef __EMSCRIPTEN__
@ -163,18 +179,24 @@ char *make_path(const char *file) {
return pathbuf;
}
unsigned char *slurp_file(const char *filename, size_t *size)
void *cdb_slurp(struct cdb *cdb, const char *file, size_t *size)
{
if (cdb_find(&game_cdb, filename, strlen(filename))) {
unsigned vlen, vpos;
vpos = cdb_datapos(&game_cdb);
vlen = cdb_datalen(&game_cdb);
vpos = cdb_datapos(cdb);
vlen = cdb_datalen(cdb);
char *data = malloc(vlen);
cdb_read(&game_cdb, data, vlen, vpos);
cdb_read(cdb, data, vlen, vpos);
if (size) *size = vlen;
return data;
}
unsigned char *slurp_file(const char *filename, size_t *size)
{
if (cdb_find(&game_cdb, filename, strlen(filename)))
return cdb_slurp(&game_cdb, filename, size);
else if (cdb_find(&corecdb, filename, strlen(filename)))
return cdb_slurp(&corecdb, filename, size);
FILE *f;
jump:
@ -197,7 +219,7 @@ unsigned char *slurp_file(const char *filename, size_t *size)
char *slurp_text(const char *filename, size_t *size)
{
size_t len;
char *str = slurp_file(filename, &len);
unsigned char *str = slurp_file(filename, &len);
if (!str) return NULL;
char *retstr = malloc(len+1);
memcpy(retstr, str, len);

View file

@ -19,6 +19,8 @@ unsigned char *slurp_file(const char *filename, size_t *size);
char *slurp_text(const char *filename, size_t *size);
int slurp_write(const char *txt, const char *filename);
char *seprint(char *fmt, ...);
void pack_engine(const char *fname);
#endif

View file

@ -45,6 +45,9 @@ void script_startup() {
for (int i = 0; i < 100; i++)
num_cache[i] = int2js(i);
script_dofile("scripts/engine.js");
// jso_file("scripts/engine.js");
}
JSValue num_cache[100] = {0};
@ -95,13 +98,13 @@ void script_evalf(const char *format, ...)
JS_FreeValue(js,obj);
}
uint8_t *compile_script(const char *file) {
size_t len;
const char *script = slurp_text(file, &len);
JSValue obj = JS_Eval(js, script, len, file, JS_EVAL_FLAG_COMPILE_ONLY | JS_EVAL_TYPE_GLOBAL | JS_EVAL_FLAGS);
uint8_t *compile_script(const char *file, size_t *len) {
const char *script = slurp_text(file, len);
JSValue obj = JS_Eval(js, script, *len, file, JS_EVAL_FLAG_COMPILE_ONLY | JS_EVAL_TYPE_GLOBAL | JS_EVAL_FLAGS);
free(script);
size_t out_len;
uint8_t *out;
return JS_WriteObject(js, &out_len, obj, JS_WRITE_OBJ_BYTECODE);
uint8_t *out = JS_WriteObject(js, &out_len, obj, JS_WRITE_OBJ_BYTECODE);
return out;
}
struct callee stacktrace_callee;
@ -127,6 +130,25 @@ int script_dofile(const char *file) {
return file_mod_secs(file);
}
JSValue script_runjso(const uint8_t *buf, size_t len)
{
JSValue obj = JS_ReadObject(js, buf, len, JS_EVAL_FLAGS);
JSValue ret = JS_EvalFunction(js, obj);
js_print_exception(ret);
return ret;
}
time_t jso_file(const char *file)
{
size_t len;
uint8_t *byte = compile_script(file, &len);
JSValue obj = JS_ReadObject(js, byte, len, JS_READ_OBJ_BYTECODE);
JSValue ret = JS_EvalFunction(js, obj);
js_print_exception(ret);
free(byte);
return file_mod_secs(file);
}
JSValue script_runfile(const char *file)
{
size_t len;

View file

@ -20,6 +20,7 @@ void script_startup();
void script_run(const char *script, const char *file);
void script_evalf(const char *format, ...);
int script_dofile(const char *file);
time_t jso_file(const char *file);
JSValue script_runfile(const char *file);
void script_update(double dt);
void script_draw();
@ -57,6 +58,6 @@ void call_physics(double dt);
void register_draw(struct callee c);
void call_draw();
uint8_t *compile_script(const char *file);
uint8_t *compile_script(const char *file, size_t *len);
#endif

View file

@ -292,13 +292,13 @@ static void _sg_metal_encode_texture_pixels(int x, int y, int w, int h, bool ori
[cmd_buffer waitUntilCompleted];
MTLRegion mtl_region = MTLRegionMake2D(0, 0, w, h);
void* temp_pixels = (void*)SOKOL_MALLOC(w * 4 * h);
void* temp_pixels = malloc(w * 4 * h);
SOKOL_ASSERT(temp_pixels);
[mtl_dst_texture getBytes:temp_pixels bytesPerRow:w * 4 fromRegion:mtl_region mipmapLevel:0];
// int res = SDL_ConvertPixels(w, h, _sg_metal_texture_format_to_sdl_pixel_format(mtl_dst_texture_desc.pixelFormat), temp_pixels, w * 4, SDL_PIXELFORMAT_RGBA32, pixels, w * 4);
SOKOL_FREE(temp_pixels);
SOKOL_ASSERT(res == 0);
_SOKOL_UNUSED(res);
free(temp_pixels);
// SOKOL_ASSERT(res == 0);
// _SOKOL_UNUSED(res);
}
static void _sg_metal_query_image_pixels(_sg_image_t* img, void* pixels) {

View file

@ -1,184 +0,0 @@
2006-06-29 Michael Tokarev <mjt@corpit.ru>
* see debian/changelog file for further changes.
2005-04-18 Michael Tokarev <mjt@corpit.ru>
* move cdb_make_find.c content into cdb_make_put.c
* introduce CDB_PUT_REPLACE0 - zerofill old duplicates
* allow usage of cdb.h in C++
2005-04-11 Michael Tokarev <mjt@corpit.ru>
* do not autogenerate files (cdb.h.in, cdb.3.in etc), but
use real files instead (only substituted VERSION and NAME)
* finally fixed the `!fputs()' condition to be `fputs() < 0'
as it should be in cdb.c (misbehaves on *bsd)
* kill cdbi_t usage in cdb_int.h
* export _cdb_make_fullwrite() (was ewrite()) and _cdb_make_flush()
and use them in cdb_make.c as appropriate
* almost completely rewrite _cdb_make_find() and friends:
- _cdb_make_find() now accepts new parameter, remove (bool), which,
if true, indicates all found records should be deleted from the
database.
- Call _cdb_make_find() with remove=0 from cdb_make_exists()
- Call _cdb_make_find() with appropriate arguments from
cdb_make_put(), and simplify the latter greatly (was too clumsy
anyway)
* rename `flags' parameter in cdb_make_put() to be `mode' which is
more appropriate
* change #if conditional in nss_cdb.c
from __GLIBC__ to __GNU_LIBRARY__
2003-11-04 Michael Tokarev <mjt@corpit.ru>
* added cdb_get() routine: tinycdb officially uses mmap.
* added cdb_{get,read}{data,key}() macros to read and get
current data and key.
* fixed bug in cdb_seek() - incorrect wrap, sometimes
cdb_seek()+cdb_bread() may return EIO instead of finding
correct record.
* added some tweaks to Makefile to build position-independent
libcdb_pic.a and shared libcdb.so libraries. Note that
using libcdb as shared library is probably not a good idea,
due to tiny size of the library.
* added initial nss_cdb module. Still not well-tested.
Probably will not build on non-GNU system.
* adjusted tests.{ok,sh} for latest cdb utility modifications
(-a mode in query by default)
* Victor Porton (porton at ex-code.com) provided a patch
to allow tinycdb to be built on win32 platform (cdb_init.c).
Completely untested.
2003-08-13 Michael Tokarev <mjt@corpit.ru>
* s/cdbi_t/unsigned/g. No need to keep this type.
* changed usage of cdb_findnext(): one need to pass
pointer to cdb structure to cdb_findnext() now,
and should use cdb_datapos(struct cdb_find *)
instead of cdb_datapos(struct cdb *)
* added cdb_seqinit() and cdb_seqnext() routines for sequential
record enumeration
* addded cdb_dend to the cdb structure: end of data
position. Use that in cdb_seq*().
* more strict checking: ensure data is within data section,
and hash tables are within hash section of a file.
* cdb_make.c (cdb_make_start): zerofill cdb_make structure
to shut valgrind up (writing uninitialized data to file)
* cdb.c (cmode): always open file in RDWR mode to allow
duplicate key detection
2002-12-08 Michael Tokarev <mjt+cdb@corpit.ru>
* version 0.73
* de-Debianization. Oh well... ;)
* no code changes, just like in 0.72
2002-10-13 Michael Tokarev <mjt+cdb@corpit.ru>
* version 0.72
* cleaned up debian packaging and made it actually work
* no code changes
2002-07-22 Michael Tokarev <mjt+cdb@corpit.ru>
* version 0.71
* rearranged object files to not depend on ranlib on
systems that requires it (i.e. OpenBSD)
* use ranlib but mark it's possible error as non-fatal
2001-12-10 Michael Tokarev <mjt+cdb@corpit.ru>
* version 0.7a
* converted to CVS, added two missing #include <stdlib.h> for
malloc declaration and spec target to the Makefile
2001-10-14 Michael Tokarev <mjt+cdb@corpit.ru>
* version 0.7
* added cdb_seek() and cdb_bread() routines as found
in freecdb/cdb-0.64
2001-07-26 Michael Tokarev <mjt+cdb@corpit.ru>
* version 0.6
* added another option, CDB_PUT_WARN, to cdb_make_put's flags
(to allow adding unconditionally but still warn about dups),
now cdb_make_put seems to be logically complete.
* added and documented -r and -u options for cdb(1) command,
and made them consistent with -w and -e also.
* reorganized cdb(1) manpage and added changes made to cdb
command.
* added version references to manpages (and make them autogenerated
to simplify maintenance).
* added cdb(5) manpage describing CDB file format.
2001-07-25 Michael Tokarev <mjt+cdb@corpit.ru>
* version 0.5
* added missing #include <sys/types.h> in cdb_init.c, thanks to
ppetru@ppetru.net (Petru Paler)
* removed usage of pread() in cdb_make_find() and friends,
suggested by Liviu Daia <Liviu.Daia@imar.ro>
* autogenerate tinycdb.spec file from template and debian/changelog
* autogenerate cdb.h from cdb.h.in (substituting version)
2001-06-29 Michael Tokarev <mjt+cdb@corpit.ru>
* version 0.4
* added cdb_make_put() routine to conditionnaly add a record
* split cdb library to more files (finer granularity)
* added cdb_findinit() and cdb_findnext() routines
* renamed cdbtool to cdb
* simplified cdb utility (dropped various format spec, changed
options parsing) and a manpage
* added small note and copyright to every file in package
* added some testsuite (make test)
2001-05-27 Michael Tokarev <mjt+cdb@corpit.ru>
* version 0.3
* Initial Release.

View file

@ -1,88 +0,0 @@
# tinycdb.spec: tinycdb RPM spec file.
#
# This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
# Public domain.
Summary: A package for maintenance of constant databases
Name: tinycdb
Version: 0.78
Release: 1
Source: ftp://ftp.corpit.ru/pub/tinycdb/tinycdb_%version.tar.gz
License: Public Domain
Group: System Environment/Libraries
Prefix: %{_prefix}
BuildRoot: %{_tmppath}/%{name}-root
Summary: TinyCDB - a Constant DataBase
%description
tinycdb is a small, fast and reliable utility set and subroutine
library for creating and reading constant databases. The database
structure is tuned for fast reading:
+ Successful lookups take normally just two disk accesses.
+ Unsuccessful lookups take only one disk access.
+ Small disk space and memory size requirements; a database
uses 2048 bytes for the header and 24 bytes plus size of
(key,value) per record.
+ Maximum database size is 4GB; individual record size is not
otherwise limited.
+ Portable file format.
+ Fast creation of new databases.
+ No locking, updates are atomical.
This package contains both the utility and the development
files, together with nss_cdb module.
%package devel
Summary: Development files for the tinycdb library.
Group: System Environment/Libraries
Requires: %name = %version-%release
Summary: Development files for tinycdb
%description devel
tinycdb is a small, fast and reliable utility set and subroutine
library for creating and reading constant databases.
This package contains tinycdb development libraries and header files.
%prep
%setup -q
%build
make CFLAGS="$RPM_OPT_FLAGS" \
staticlib sharedlib cdb-shared nss \
sysconfdir=/etc
%install
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT
%makeinstall DESTDIR=$RPM_BUILD_ROOT \
libdir=%_libdir bindir=%_bindir mandir=%_mandir \
syslibdir=/%_lib sysconfdir=/etc \
includedir=%_includedir \
install-all install-nss install-piclib install-sharedlib \
INSTALLPROG=cdb-shared CP="cp -p"
%files
%defattr(-,root,root)
%_bindir/*
%_mandir/man1/*
%_mandir/man5/*
%_libdir/libcdb.so.*
/%_lib/libnss_cdb*
/etc/cdb-Makefile
%doc ChangeLog NEWS debian/changelog
%files devel
%defattr(-,root,root)
%_libdir/libcdb.a
%_libdir/libcdb_pic.a
%_libdir/libcdb.so
%_mandir/man3/*
%_includedir/*
%clean
rm -rf $RPM_BUILD_ROOT
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%changelog

View file

@ -0,0 +1,175 @@
#! /usr/bin/make -rf
# Makefile: make file for tinycdb package
#
# This file is a part of tinycdb package by Michael Tokarev, mjt+cdb@corpit.ru.
# Public domain.
VERSION = 0.80
prefix=/usr/local
exec_prefix=$(prefix)
bindir=$(exec_prefix)/bin
libdir=$(exec_prefix)/lib
syslibdir=$(libdir)
sysconfdir=/etc
includedir=$(prefix)/include
mandir=$(prefix)/man
NSSCDB_DIR = $(sysconfdir)
DESTDIR=
CC = cc
CFLAGS = -O
CDEFS = -D_FILE_OFFSET_BITS=64
LD = $(CC)
LDFLAGS =
AR = ar
ARFLAGS = rv
RANLIB = ranlib
NSS_CDB = libnss_cdb.so.2
LIBBASE = libcdb
LIB = $(LIBBASE).a
PICLIB = $(LIBBASE)_pic.a
SHAREDLIB = $(LIBBASE).so.1
SOLIB = $(LIBBASE).so
CDB_USELIB = $(LIB)
NSS_USELIB = $(PICLIB)
LIBMAP = $(LIBBASE).map
INSTALLPROG = cdb
# The following assumes GNU CC/LD -
# used for building shared libraries only
CFLAGS_PIC = -fPIC
LDFLAGS_SHARED = -shared
LDFLAGS_SONAME = -Wl,--soname=
LDFLAGS_VSCRIPT = -Wl,--version-script=
CP = cp
LIB_SRCS = cdb_init.c cdb_find.c cdb_findnext.c cdb_seq.c cdb_seek.c \
cdb_pack.c cdb_unpack.c \
cdb_make_add.c cdb_make_put.c cdb_make.c cdb_hash.c
NSS_SRCS = nss_cdb.c nss_cdb-passwd.c nss_cdb-group.c nss_cdb-spwd.c
NSSMAP = nss_cdb.map
DISTFILES = Makefile cdb.h cdb_int.h $(LIB_SRCS) cdb.c \
$(NSS_SRCS) nss_cdb.h nss_cdb-Makefile \
cdb.3 cdb.1 cdb.5 \
tinycdb.spec tests.sh tests.ok \
$(LIBMAP) $(NSSMAP) \
NEWS
all: static
static: staticlib cdb
staticlib: $(LIB)
nss: $(NSS_CDB)
piclib: $(PICLIB)
sharedlib: $(SHAREDLIB)
shared: sharedlib cdb-shared
LIB_OBJS = $(LIB_SRCS:.c=.o)
LIB_OBJS_PIC = $(LIB_SRCS:.c=.lo)
NSS_OBJS = $(NSS_SRCS:.c=.lo)
$(LIB): $(LIB_OBJS)
-rm -f $@
$(AR) $(ARFLAGS) $@ $(LIB_OBJS)
-$(RANLIB) $@
$(PICLIB): $(LIB_OBJS_PIC)
-rm -f $@
$(AR) $(ARFLAGS) $@ $(LIB_OBJS_PIC)
-$(RANLIB) $@
$(SHAREDLIB): $(LIB_OBJS_PIC) $(LIBMAP)
-rm -f $(SOLIB)
ln -s $@ $(SOLIB)
$(LD) $(LDFLAGS) $(LDFLAGS_SHARED) -o $@ \
$(LDFLAGS_SONAME)$(SHAREDLIB) $(LDFLAGS_VSCRIPT)$(LIBMAP) \
$(LIB_OBJS_PIC)
cdb: cdb.o $(CDB_USELIB)
$(LD) $(LDFLAGS) -o $@ cdb.o $(CDB_USELIB)
cdb-shared: cdb.o $(SHAREDLIB)
$(LD) $(LDFLAGS) -o $@ cdb.o $(SHAREDLIB)
$(NSS_CDB): $(NSS_OBJS) $(NSS_USELIB) $(NSSMAP)
$(LD) $(LDFLAGS) $(LDFLAGS_SHARED) -o $@ \
$(LDFLAGS_SONAME)$@ $(LDFLAGS_VSCRIPT)$(NSSMAP) \
$(NSS_OBJS) $(NSS_USELIB)
.SUFFIXES:
.SUFFIXES: .c .o .lo
.c.o:
$(CC) $(CFLAGS) $(CDEFS) -c $<
.c.lo:
$(CC) $(CFLAGS) $(CDEFS) $(CFLAGS_PIC) -c -o $@ -DNSSCDB_DIR=\"$(NSSCDB_DIR)\" $<
cdb.o: cdb.h
$(LIB_OBJS) $(LIB_OBJS_PIC): cdb_int.h cdb.h
$(NSS_OBJS): nss_cdb.h cdb.h
clean:
-rm -f *.o *.lo core *~ tests.out tests-shared.ok
realclean distclean: clean
-rm -f $(LIBBASE)[._][aps]* $(NSS_CDB)* cdb cdb-shared
test tests check: cdb
sh ./tests.sh ./cdb > tests.out 2>&1
diff tests.ok tests.out
@echo All tests passed
test-shared tests-shared check-shared: cdb-shared
sed 's/^cdb: /cdb-shared: /' <tests.ok >tests-shared.ok
LD_LIBRARY_PATH=. sh ./tests.sh ./cdb-shared > tests.out 2>&1
diff tests-shared.ok tests.out
rm -f tests-shared.ok
@echo All tests passed
do_install = \
while [ "$$1" ] ; do \
if [ .$$4 = .- ]; then f=$$1; else f=$$4; fi; \
d=$(DESTDIR)$$3 ; echo installing $$1 to $$d/$$f; \
[ -d $$d ] || mkdir -p $$d || exit 1 ; \
$(CP) $$1 $$d/$$f || exit 1; \
chmod 0$$2 $$d/$$f || exit 1; \
shift 4; \
done
install-all: all $(INSTALLPROG)
set -- \
cdb.h 644 $(includedir) - \
cdb.3 644 $(mandir)/man3 - \
cdb.1 644 $(mandir)/man1 - \
cdb.5 644 $(mandir)/man5 - \
$(INSTALLPROG) 755 $(bindir) cdb \
libcdb.a 644 $(libdir) - \
; \
$(do_install)
install-nss: nss
@set -- $(NSS_CDB) 644 $(syslibdir) - \
nss_cdb-Makefile 644 $(sysconfdir) cdb-Makefile ; \
$(do_install)
install-sharedlib: sharedlib
@set -- $(SHAREDLIB) 644 $(libdir) - ; \
$(do_install) ; \
ln -sf $(SHAREDLIB) $(DESTDIR)$(libdir)/$(LIBBASE).so
install-piclib: piclib
@set -- $(PICLIB) 644 $(libdir) - ; \
$(do_install)
install: install-all
DNAME = tinycdb-$(VERSION)
dist: ../$(DNAME).tar.gz
../$(DNAME).tar.gz: $(DISTFILES)
mkdir $(DNAME)
ln $(DISTFILES) $(DNAME)/
rm -f $@
tar cfz $@ $(DNAME)
rm -fr $(DNAME)
.PHONY: all clean realclean dist spec
.PHONY: test tests check test-shared tests-shared check-shared
.PHONY: static staticlib shared sharedlib nss piclib
.PHONY: install install-all install-sharedlib install-piclib install-nss

View file

@ -1,5 +1,35 @@
User-visible news. Latest at the top.
tinycdb-0.80 2023-09-17
- bugfix: cdb utility: check return value from close() too,
when creating the cdb file
- portability: cdb utility: ignore SIGXFSZ signal if defined,
to be able to clean up when exceeding file limit
- robustness: let cdb_make_start to lseek() to the zero position
of file. This ensures the file is seekable right at the start
instead of at the very end, too
- robustness: cdb utility: remove temporary file in case create
operation fails
- portability use SEE_SET macro instead of 0 for lseek()
- split out cdb_pack() into its own .c file
tinycdb-0.79 2023-09-17
- bugfix: call fsync() at the end of cdb_make_finish()
to ensure data does not stay in some kernel buffer
- bugfix: clean tests.out in `make distclean' too
- `make dist' makes tarball in the parent dir
- stop shipping debian/* - it is not a native debian package
tinycdb-0.78 2012-05-11
- bugfix release:

View file

@ -1,11 +1,11 @@
/* cdb.h: public cdb include file
*
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
* This file is a part of tinycdb package by Michael Tokarev, mjt+cdb@corpit.ru.
* Public domain.
*/
#ifndef TINYCDB_VERSION
#define TINYCDB_VERSION 0.78
#define TINYCDB_VERSION 0.80
#ifdef __cplusplus
extern "C" {
@ -37,6 +37,7 @@ struct cdb {
#define cdb_fileno(c) ((c)->cdb_fd)
int cdb_init(struct cdb *cdbp, int fd);
int cdb_initf(struct cdb *cdbp, void *p, unsigned len);
void cdb_free(struct cdb *cdbp);
int cdb_read(const struct cdb *cdbp,

View file

@ -1,6 +1,6 @@
/* cdb_find.c: cdb_find routine
*
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
* This file is a part of tinycdb package by Michael Tokarev, mjt+cdb@corpit.ru.
* Public domain.
*/

View file

@ -1,6 +1,6 @@
/* cdb_findnext.c: sequential cdb_find routines
*
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
* This file is a part of tinycdb package by Michael Tokarev, mjt+cdb@corpit.ru.
* Public domain.
*/

View file

@ -1,6 +1,6 @@
/* cdb_hash.c: cdb hashing routine
*
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
* This file is a part of tinycdb package by Michael Tokarev, mjt+cdb@corpit.ru.
* Public domain.
*/

View file

@ -1,6 +1,6 @@
/* cdb_init.c: cdb_init, cdb_free and cdb_read routines
*
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
* This file is a part of tinycdb package by Michael Tokarev, mjt+cdb@corpit.ru.
* Public domain.
*/
@ -16,6 +16,27 @@
#include <sys/stat.h>
#include "cdb_int.h"
int cdb_initf(struct cdb *cdbp, void *p, unsigned len)
{
/* get file size */
if (len < 0)
return -1;
cdbp->cdb_fd = -1;
cdbp->cdb_fsize = len;
cdbp->cdb_mem = p;
cdbp->cdb_vpos = cdbp->cdb_vlen = 0;
cdbp->cdb_kpos = cdbp->cdb_klen = 0;
unsigned dend;
unsigned fsize = len;
dend = cdb_unpack(p);
if (dend < 2048) dend = 2048;
else if (dend >= fsize) dend = fsize;
cdbp->cdb_dend = dend;
return 0;
}
int
cdb_init(struct cdb *cdbp, int fd)
{

View file

@ -1,6 +1,6 @@
/* cdb_int.h: internal cdb library declarations
*
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
* This file is a part of tinycdb package by Michael Tokarev, mjt+cdb@corpit.ru.
* Public domain.
*/

View file

@ -1,6 +1,6 @@
/* cdb_make.c: basic cdb creation routines
*
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
* This file is a part of tinycdb package by Michael Tokarev, mjt+cdb@corpit.ru.
* Public domain.
*/
@ -9,15 +9,6 @@
#include <string.h>
#include "cdb_int.h"
void
cdb_pack(unsigned num, unsigned char buf[4])
{
buf[0] = num & 255; num >>= 8;
buf[1] = num & 255; num >>= 8;
buf[2] = num & 255;
buf[3] = num >> 8;
}
int
cdb_make_start(struct cdb_make *cdbmp, int fd)
{
@ -25,7 +16,7 @@ cdb_make_start(struct cdb_make *cdbmp, int fd)
cdbmp->cdb_fd = fd;
cdbmp->cdb_dpos = 2048;
cdbmp->cdb_bpos = cdbmp->cdb_buf + 2048;
return 0;
return lseek(fd, 0, SEEK_SET);
}
int internal_function
@ -152,11 +143,11 @@ cdb_make_finish_internal(struct cdb_make *cdbmp)
cdb_pack(hpos[t], p + (t << 3));
cdb_pack(hcnt[t], p + (t << 3) + 4);
}
if (lseek(cdbmp->cdb_fd, 0, 0) != 0 ||
if (lseek(cdbmp->cdb_fd, 0, SEEK_SET) != 0 ||
_cdb_make_fullwrite(cdbmp->cdb_fd, p, 2048) != 0)
return -1;
return 0;
return fsync(cdbmp->cdb_fd);
}
static void

View file

@ -1,6 +1,6 @@
/* cdb_make_add.c: basic cdb_make_add routine
*
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
* This file is a part of tinycdb package by Michael Tokarev, mjt+cdb@corpit.ru.
* Public domain.
*/

View file

@ -1,6 +1,6 @@
/* cdb_make_put.c: "advanced" cdb_make_put routine
*
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
* This file is a part of tinycdb package by Michael Tokarev, mjt+cdb@corpit.ru.
* Public domain.
*/

View file

@ -0,0 +1,16 @@
/* cdb_pack.c: pack a 32bit integer (to network byte order)
*
* This file is a part of tinycdb package by Michael Tokarev, mjt+cdb@corpit.ru.
* Public domain.
*/
#include "cdb.h"
void
cdb_pack(unsigned num, unsigned char buf[4])
{
buf[0] = num & 255; num >>= 8;
buf[1] = num & 255; num >>= 8;
buf[2] = num & 255;
buf[3] = num >> 8;
}

View file

@ -1,6 +1,6 @@
/* cdb_seek.c: old interface for reading cdb file
*
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
* This file is a part of tinycdb package by Michael Tokarev, mjt+cdb@corpit.ru.
* Public domain.
*/

View file

@ -1,6 +1,6 @@
/* cdb_seq.c: sequential record retrieval routines
*
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
* This file is a part of tinycdb package by Michael Tokarev, mjt+cdb@corpit.ru.
* Public domain.
*/

View file

@ -1,6 +1,6 @@
/* cdb_unpack.c: unpack 32bit integer
/* cdb_unpack.c: unpack a 32bit integer from network byte order
*
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
* This file is a part of tinycdb package by Michael Tokarev, mjt+cdb@corpit.ru.
* Public domain.
*/

View file

@ -0,0 +1,83 @@
Create simple db
0
checksum may fail if no md5sum program
97549c2e76e2d446430a392d77ed1bcb
Dump simple db
+3,4:one->here
+1,1:a->b
+1,3:b->abc
+3,4:one->also
0
Stats for simple db
number of records: 4
key min/avg/max length: 1/2/3
val min/avg/max length: 1/3/4
hash tables/entries/collisions: 3/8/1
hash table min/avg/max length: 2/3/4
hash table distances:
d0: 3 75%
d1: 1 25%
d2: 0 0%
d3: 0 0%
d4: 0 0%
d5: 0 0%
d6: 0 0%
d7: 0 0%
d8: 0 0%
d9: 0 0%
>9: 0 0%
0
Query simple db (two records match)
herealso
0
Query for non-existed key
100
Doing 600 repeated records
0
checksum may fail if no md5sum program
412a0b7578efca528bf8398c8811caf4
cdb stats should show 601 record
number of records: 601
key min/avg/max length: 1/1/1
val min/avg/max length: 3/3/5
hash tables/entries/collisions: 2/1202/599
hash table min/avg/max length: 2/601/1200
hash table distances:
d0: 2 0%
d1: 1 0%
d2: 1 0%
d3: 1 0%
d4: 1 0%
d5: 1 0%
d6: 1 0%
d7: 1 0%
d8: 1 0%
d9: 1 0%
>9: 590 98%
0
Querying key
other
0
Dumping and re-creating db
0
0
Handling large key size
cdb: (stdin): bad format
2
Handling large value size
cdb: (stdin): bad format
2
Handling invalid input format (short file)
cdb: unable to read: short file
2
Creating db with eol in key and value
0
checksum may fail if no md5sum program
1d444fe759c26d36f500d01c41cfda40
Querying key-value with eol
b
0
Handling file size limits
cdb: cdb_make_put: File too large
111

143
source/engine/thirdparty/tinycdb/tests.sh vendored Executable file
View file

@ -0,0 +1,143 @@
#! /bin/sh
# tests.sh: This script will run tests for cdb.
# Execute with ./tests.sh ./cdb
# (first arg if present gives path to cdb tool to use, default is `cdb').
#
# This file is a part of tinycdb package by Michael Tokarev, mjt+cdb@corpit.ru.
# Public domain.
case "$1" in
"") cdb=cdb ;;
*) cdb="$1" ;;
esac
do_csum() {
echo checksum may fail if no md5sum program
md5sum $1 | sed -e 's|[ ].*||' -e 'y|[ABCDEF]|[abcdef]|'
}
rm -f 1.cdb 1a.cdb
echo Create simple db
echo "+3,4:one->here
+1,1:a->b
+1,3:b->abc
+3,4:one->also
" | $cdb -c 1.cdb
echo $?
do_csum 1.cdb
echo Dump simple db
$cdb -d 1.cdb
echo $?
echo Stats for simple db
$cdb -s 1.cdb
echo $?
echo "Query simple db (two records match)"
$cdb -q 1.cdb one
echo "
$?"
echo Query for non-existed key
$cdb -q 1.cdb none
echo $?
echo Doing 600 repeated records
(
for i in 0 1 2 3 4 5 ; do
for j in 0 1 2 3 4 5 6 7 8 9 ; do
for k in 0 1 2 3 4 5 6 7 8 9 ; do
echo "+1,3:a->$i$j$k"
done
done
done
echo "+1,5:b->other"
echo
) | $cdb -c 1.cdb
echo $?
do_csum 1.cdb
echo cdb stats should show 601 record
$cdb -s 1.cdb
echo $?
echo Querying key
$cdb -q 1.cdb b
echo "
"$?
echo Dumping and re-creating db
$cdb -d 1.cdb | $cdb -c 1a.cdb
echo $?
cmp 1.cdb 1a.cdb
$cdb -d -m 1.cdb | $cdb -c -m 1a.cdb
echo $?
cmp 1.cdb 1a.cdb
echo Handling large key size
echo "+123456789012,1:" | $cdb -c 1.cdb
echo $?
echo Handling large value size
echo "+1,123456789012:" | $cdb -c 1.cdb
echo $?
echo "Handling invalid input format (short file)"
echo "+10,10:" | $cdb -c 1.cdb
echo $?
echo Creating db with eol in key and value
echo "+2,2:a
->b
" | $cdb -c 1.cdb
echo $?
do_csum 1.cdb
echo Querying key-value with eol
$cdb -q 1.cdb "a
"
echo $?
echo Handling file size limits
(
ulimit -f 4
trap '' 25
(
for i in 0 1 2 3 4 5 6 7 8 9 ; do
for j in 0 1 2 3 4 5 6 7 8 9 ; do
for k in 0 1 2 3 4 5 6 7 8 9 ; do
echo "+4,4:k$i$j$k->v$i$j$k"
done
done
done
echo
) | $cdb -c 1.cdb
echo $?
)
if false ; then # does not work for now, bugs in libc
echo Handling oom condition
(
for i0 in 0 1 2 3 4 5 6 7 8 9 ; do
for i1 in 0 1 2 3 4 5 6 7 8 9 ; do
for i2 in 0 1 2 3 4 5 6 7 8 9 ; do
for i3 in 0 1 2 3 4 5 6 7 8 9 ; do
for i4 in 0 1 2 3 4 5 6 7 8 9 ; do
echo "+5,0:$i0$i1$i2$i3$i4->"
done
done
done
done
done
echo
) | (ulimit -v 1900; $cdb -c 1.cdb)
echo $?
fi
rm -rf 1.cdb 1a.cdb 1.cdb.tmp
exit 0

View file

@ -8,6 +8,8 @@
#include "sound.h"
#include "resources.h"
#include <stdio.h>
#include "datastream.h"
#include "timer.h"
@ -42,6 +44,7 @@
#include "sokol/sokol_app.h"
#include "sokol/sokol_audio.h"
#include "sokol/sokol_time.h"
#include "sokol/sokol_args.h"
#define STB_DS_IMPLEMENTATION
#include <stb_ds.h>
@ -152,7 +155,7 @@ int frame_fps() {
return 1.0/sapp_frame_duration();
}
static double low_fps = 1/24.0; /* Chosen because of apple's 24 hz mode */
static double low_fps = 1/24.0;
static double low_fps_c = 0.0;
void c_frame()
@ -356,8 +359,6 @@ sapp_desc sokol_main(int argc, char **argv) {
script_startup();
script_dofile("scripts/engine.js");
int argsize = 0;
for (int i = 0; i < argc; i++) {
argsize += strlen(argv[i]);

556
tools/cdb.c Normal file
View file

@ -0,0 +1,556 @@
/* cdb.c: cdb command line tool
*
* This file is a part of tinycdb package by Michael Tokarev, mjt+cdb@corpit.ru.
* Public domain.
*/
#define _GNU_SOURCE /* #define this even on Windows */
#ifdef _WIN32 /* by the way, how about win64? */
# include <io.h>
# include <malloc.h>
/* This pragma suppresses snippy VC warnings for POSIX functions like read() */
# pragma warning(disable: 4996)
#else
# include <unistd.h>
# include <signal.h>
#endif
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include "cdb.h"
#ifndef EPROTO
# define EPROTO EINVAL
#endif
#ifdef __GLIBC__
# define HAVE_PROGRAM_INVOCATION_SHORT_NAME
#endif
#ifdef HAVE_PROGRAM_INVOCATION_SHORT_NAME
# define progname program_invocation_short_name
#else
static char *progname;
#endif
#ifndef O_NOFOLLOW
# define O_NOFOLLOW 0
#endif
#ifdef _WIN32
# define FBINMODE "b"
#else
# define FBINMODE
#endif
#define F_DUPMASK 0x000f
#define F_WARNDUP 0x0100
#define F_ERRDUP 0x0200
#define F_MAP 0x1000 /* map format (or else CDB native format) */
/* Silly defines just to suppress silly compiler warnings.
* The thing is, trivial routines like strlen(), fgets() etc expects
* char* argument, and GCC>=4 complains about using unsigned char* here.
* Silly silly silly.
*/
#ifdef __GNUC__
static inline size_t ustrlen(const unsigned char *s) {
return strlen((const char*)s);
}
static inline unsigned char *ufgets(unsigned char *s, int size, FILE *f) {
return (unsigned char*)fgets((char*)s, size, f);
}
#else
# define ustrlen strlen
# define ufgets fgets
#endif
static unsigned char *buf;
static unsigned blen;
static char *cleanup_tmpname;
static void
#ifdef __GNUC__
__attribute__((noreturn,format(printf,2,3)))
#endif
error(int errnum, const char *fmt, ...)
{
if (fmt) {
va_list ap;
fprintf(stderr, "%s: ", progname);
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
if (errnum)
fprintf(stderr, ": %s\n", strerror(errnum));
else {
if (fmt) putc('\n', stderr);
fprintf(stderr, "%s: try `%s -h' for help\n", progname, progname);
}
fflush(stderr);
if (cleanup_tmpname)
unlink(cleanup_tmpname);
exit(errnum ? 111 : 2);
}
static void allocbuf(unsigned len) {
if (blen < len) {
buf = (unsigned char*)(buf ? realloc(buf, len) : malloc(len));
if (!buf)
error(ENOMEM, "unable to allocate %u bytes", len);
blen = len;
}
}
static int qmode(char *dbname, const char *key, int num, int flags)
{
struct cdb c;
struct cdb_find cf;
int r;
int n, found;
r = open(dbname, O_RDONLY);
if (r < 0 || cdb_init(&c, r) != 0)
error(errno, "unable to open database `%s'", dbname);
r = cdb_findinit(&cf, &c, key, strlen(key));
if (!r)
return 100;
else if (r < 0)
error(errno, "%s", key);
n = 0; found = 0;
while((r = cdb_findnext(&cf)) > 0) {
++n;
if (num && num != n) continue;
++found;
allocbuf(cdb_datalen(&c));
if (cdb_read(&c, buf, cdb_datalen(&c), cdb_datapos(&c)) != 0)
error(errno, "unable to read value");
fwrite(buf, 1, cdb_datalen(&c), stdout);
if (flags & F_MAP) putchar('\n');
if (num)
break;
}
if (r < 0)
error(0, "%s", key);
return found ? 0 : 100;
}
static void
fget(FILE *f, unsigned char *b, unsigned len, unsigned *posp, unsigned limit)
{
if (posp && limit - *posp < len)
error(EPROTO, "invalid database format");
if (fread(b, 1, len, f) != len) {
if (ferror(f)) error(errno, "unable to read");
fprintf(stderr, "%s: unable to read: short file\n", progname);
exit(2);
}
if (posp) *posp += len;
}
static int
fcpy(FILE *fi, FILE *fo, unsigned len, unsigned *posp, unsigned limit)
{
while(len > blen) {
fget(fi, buf, blen, posp, limit);
if (fo && fwrite(buf, 1, blen, fo) != blen) return -1;
len -= blen;
}
if (len) {
fget(fi, buf, len, posp, limit);
if (fo && fwrite(buf, 1, len, fo) != len) return -1;
}
return 0;
}
static int
dmode(char *dbname, char mode, int flags)
{
unsigned eod, klen, vlen;
unsigned pos = 0;
FILE *f;
if (strcmp(dbname, "-") == 0)
f = stdin;
else if ((f = fopen(dbname, "r" FBINMODE)) == NULL)
error(errno, "open %s", dbname);
allocbuf(2048);
fget(f, buf, 2048, &pos, 2048);
eod = cdb_unpack(buf);
while(pos < eod) {
fget(f, buf, 8, &pos, eod);
klen = cdb_unpack(buf);
vlen = cdb_unpack(buf + 4);
if (!(flags & F_MAP))
if (printf(mode == 'd' ? "+%u,%u:" : "+%u:", klen, vlen) < 0) return -1;
if (fcpy(f, stdout, klen, &pos, eod) != 0) return -1;
if (mode == 'd')
if (fputs(flags & F_MAP ? " " : "->", stdout) < 0)
return -1;
if (fcpy(f, mode == 'd' ? stdout : NULL, vlen, &pos, eod) != 0)
return -1;
if (putc('\n', stdout) < 0)
return -1;
}
if (pos != eod)
error(EPROTO, "invalid cdb file format");
if (!(flags & F_MAP))
if (putc('\n', stdout) < 0)
return -1;
return 0;
}
static int smode(char *dbname) {
FILE *f;
unsigned pos, eod;
unsigned cnt = 0;
unsigned kmin = 0, kmax = 0, ktot = 0;
unsigned vmin = 0, vmax = 0, vtot = 0;
unsigned hmin = 0, hmax = 0, htot = 0, hcnt = 0;
#define NDIST 11
unsigned dist[NDIST];
unsigned char toc[2048];
unsigned k;
if (strcmp(dbname, "-") == 0)
f = stdin;
else if ((f = fopen(dbname, "r" FBINMODE)) == NULL)
error(errno, "open %s", dbname);
pos = 0;
fget(f, toc, 2048, &pos, 2048);
allocbuf(2048);
eod = cdb_unpack(toc);
while(pos < eod) {
unsigned klen, vlen;
fget(f, buf, 8, &pos, eod);
klen = cdb_unpack(buf);
vlen = cdb_unpack(buf + 4);
fcpy(f, NULL, klen, &pos, eod);
fcpy(f, NULL, vlen, &pos, eod);
++cnt;
ktot += klen;
if (!kmin || kmin > klen) kmin = klen;
if (kmax < klen) kmax = klen;
vtot += vlen;
if (!vmin || vmin > vlen) vmin = vlen;
if (vmax < vlen) vmax = vlen;
vlen += klen;
}
if (pos != eod) error(EPROTO, "invalid cdb file format");
for (k = 0; k < NDIST; ++k)
dist[k] = 0;
for (k = 0; k < 256; ++k) {
unsigned i = cdb_unpack(toc + (k << 3));
unsigned hlen = cdb_unpack(toc + (k << 3) + 4);
if (i != pos) error(EPROTO, "invalid cdb hash table");
if (!hlen) continue;
for (i = 0; i < hlen; ++i) {
unsigned h;
fget(f, buf, 8, &pos, 0xffffffff);
if (!cdb_unpack(buf + 4)) continue;
h = (cdb_unpack(buf) >> 8) % hlen;
if (h == i) h = 0;
else {
if (h < i) h = i - h;
else h = hlen - h + i;
if (h >= NDIST) h = NDIST - 1;
}
++dist[h];
}
if (!hmin || hmin > hlen) hmin = hlen;
if (hmax < hlen) hmax = hlen;
htot += hlen;
++hcnt;
}
printf("number of records: %u\n", cnt);
printf("key min/avg/max length: %u/%u/%u\n",
kmin, cnt ? (ktot + cnt / 2) / cnt : 0, kmax);
printf("val min/avg/max length: %u/%u/%u\n",
vmin, cnt ? (vtot + cnt / 2) / cnt : 0, vmax);
printf("hash tables/entries/collisions: %u/%u/%u\n",
hcnt, htot, cnt - dist[0]);
printf("hash table min/avg/max length: %u/%u/%u\n",
hmin, hcnt ? (htot + hcnt / 2) / hcnt : 0, hmax);
printf("hash table distances:\n");
for(k = 0; k < NDIST; ++k)
printf(" %c%u: %6u %2u%%\n",
k == NDIST - 1 ? '>' : 'd', k == NDIST - 1 ? k - 1 : k,
dist[k], cnt ? dist[k] * 100 / cnt : 0);
return 0;
}
static void badinput(const char *fn) {
fprintf(stderr, "%s: %s: bad format\n", progname, fn);
exit(2);
}
static int getnum(FILE *f, unsigned *np, const char *fn) {
unsigned n;
int c = getc(f);
if (c < '0' || c > '9') badinput(fn);
n = c - '0';
while((c = getc(f)) >= '0' && c <= '9') {
c -= '0';
if (0xffffffff / 10 - c < n) badinput(fn);
n = n * 10 + c;
}
*np = n;
return c;
}
static void
addrec(struct cdb_make *cdbmp,
const unsigned char *key, unsigned klen,
const unsigned char *val, unsigned vlen,
int flags)
{
int r = cdb_make_put(cdbmp, key, klen, val, vlen, flags & F_DUPMASK);
if (r < 0)
error(errno, "cdb_make_put");
else if (r && (flags & F_WARNDUP)) {
fprintf(stderr, "%s: key `", progname);
fwrite(key, 1, klen, stderr);
fputs("' duplicated\n", stderr);
if (flags & F_ERRDUP)
exit(1);
}
}
static void
dofile_cdb(struct cdb_make *cdbmp, FILE *f, const char *fn, int flags)
{
unsigned klen, vlen;
int c;
while((c = getc(f)) == '+') {
if ((c = getnum(f, &klen, fn)) != ',' ||
(c = getnum(f, &vlen, fn)) != ':' ||
0xffffffff - klen < vlen)
badinput(fn);
allocbuf(klen + vlen);
fget(f, buf, klen, NULL, 0);
if (getc(f) != '-' || getc(f) != '>') badinput(fn);
fget(f, buf + klen, vlen, NULL, 0);
if (getc(f) != '\n') badinput(fn);
addrec(cdbmp, buf, klen, buf + klen, vlen, flags);
}
if (c != '\n') badinput(fn);
}
static void
dofile_ln(struct cdb_make *cdbmp, FILE *f, int flags)
{
unsigned char *k, *v;
while(ufgets(buf, blen, f) != NULL) {
unsigned l = 0;
for (;;) {
l += ustrlen(buf + l);
v = buf + l;
if (v > buf && v[-1] == '\n') {
v[-1] = '\0';
break;
}
if (l < blen)
allocbuf(l + 512);
if (!ufgets(buf + l, blen - l, f))
break;
}
k = buf;
while(*k == ' ' || *k == '\t') ++k;
if (!*k || *k == '#')
continue;
v = k;
while(*v && *v != ' ' && *v != '\t') ++v;
if (*v) *v++ = '\0';
while(*v == ' ' || *v == '\t') ++v;
addrec(cdbmp, k, ustrlen(k), v, ustrlen(v), flags);
}
}
static void
dofile(struct cdb_make *cdbmp, FILE *f, const char *fn, int flags)
{
if (flags & F_MAP)
dofile_ln(cdbmp, f, flags);
else
dofile_cdb(cdbmp, f, fn, flags);
if (ferror(f))
error(errno, "read error");
}
static int
cmode(char *dbname, char *tmpname, int argc, char **argv, int flags, int perms)
{
struct cdb_make cdb;
int fd;
if (!tmpname) {
tmpname = (char*)malloc(strlen(dbname) + 5);
if (!tmpname)
error(ENOMEM, "unable to allocate memory");
/* OpenBSD compiler complains about strcat() and strcpy() usage,
* and suggests to replace them with (non-standard) strlcat() and
* strlcpy(). This is silly, since it's obvious that usage of
* original str*() routines here is correct.
* This is compiler/environment bug, not tinycdb bug, so please
* fix it in proper place, and don't send patches to me. Thank you.
*/
strcat(strcpy(tmpname, dbname), ".tmp");
}
else if (strcmp(tmpname, "-") == 0 || strcmp(tmpname, dbname) == 0)
tmpname = dbname;
if (perms >= 0)
umask(0);
unlink(tmpname);
cleanup_tmpname = tmpname;
fd = open(tmpname, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW,
perms >= 0 ? perms : 0666);
if (fd < 0 || cdb_make_start(&cdb, fd) < 0)
error(errno, "unable to create %s", tmpname);
allocbuf(4096);
if (argc) {
int i;
for (i = 0; i < argc; ++i) {
if (strcmp(argv[i], "-") == 0)
dofile(&cdb, stdin, "(stdin)", flags);
else {
FILE *f = fopen(argv[i], "r");
if (!f)
error(errno, "%s", argv[i]);
dofile(&cdb, f, argv[i], flags);
fclose(f);
}
}
}
else
dofile(&cdb, stdin, "(stdin)", flags);
if (cdb_make_finish(&cdb) != 0)
error(errno, "cdb_make_finish");
if (close(fd) != 0)
error(errno, "close %s", tmpname);
if (tmpname != dbname)
if (rename(tmpname, dbname) != 0)
error(errno, "rename %s->%s", tmpname, dbname);
return 0;
}
int main(int argc, char **argv)
{
int c;
char mode = 0;
char *tmpname = NULL;
int flags = 0;
int num = 0;
int r;
int perms = -1;
extern char *optarg;
extern int optind;
#ifdef HAVE_PROGRAM_INVOCATION_SHORT_NAME
argv[0] = progname;
#else
if (argv[0] && (progname = strrchr(argv[0], '/')) != NULL)
argv[0] = ++progname;
else
progname = argv[0];
#endif
if (argc <= 1)
error(0, "no arguments given");
while((c = getopt(argc, argv, "qdlcsht:n:mwruep:0")) != EOF)
switch(c) {
case 'q': case 'd': case 'l': case 'c': case 's':
if (mode && mode != c)
error(0, "different modes of operation requested");
mode = c;
break;
case 't': tmpname = optarg; break;
case 'w': flags |= F_WARNDUP; break;
case 'e': flags |= F_WARNDUP | F_ERRDUP; break;
case 'r': flags = (flags & ~F_DUPMASK) | CDB_PUT_REPLACE; break;
case 'u': flags = (flags & ~F_DUPMASK) | CDB_PUT_INSERT; break;
case '0': flags = (flags & ~F_DUPMASK) | CDB_PUT_REPLACE0; break;
case 'm': flags |= F_MAP; break;
case 'p': {
char *ep = NULL;
perms = strtol(optarg, &ep, 0);
if (perms < 0 || perms > 0777 || (ep && *ep))
error(0, "invalid permissions `%s'", optarg);
break;
}
case 'n': {
char *ep = NULL;
if ((num = strtol(optarg, &ep, 0)) <= 0 || (ep && *ep))
error(0, "invalid record number `%s'", optarg);
break;
}
case 'h':
#define strify(x) _strify(x)
#define _strify(x) #x
printf("\
%s: Constant DataBase (CDB) tool version " strify(TINYCDB_VERSION)
". Usage is:\n\
query: %s -q [-m] [-n recno|-a] cdbfile key\n\
dump: %s -d [-m] [cdbfile|-]\n\
list: %s -l [-m] [cdbfile|-]\n\
create: %s -c [-m] [-wrue0] [-t tempfile|-] [-p perms] cdbfile [infile...]\n\
stats: %s -s [cdbfile|-]\n\
help: %s -h\n\
", progname, progname, progname, progname, progname, progname, progname);
return 0;
default:
error(0, NULL);
}
argv += optind;
argc -= optind;
#ifdef SIGXFSZ
/* at least on some linux architectures, writing past file size limit makes
* the process to receive SIGXFSZ in addition to returning -1 EFBIG
* from write(). Ignore SIGXFSZ to be able to handle write errors */
signal(SIGXFSZ, SIG_IGN);
#endif
switch(mode) {
case 'q':
if (argc < 2) error(0, "no database or key to query specified");
if (argc > 2) error(0, "extra arguments in command line");
r = qmode(argv[0], argv[1], num, flags);
break;
case 'c':
if (!argc) error(0, "no database name specified");
if ((flags & F_WARNDUP) && !(flags & F_DUPMASK))
flags |= CDB_PUT_WARN;
r = cmode(argv[0], tmpname, argc - 1, argv + 1, flags, perms);
break;
case 'd':
case 'l':
if (argc > 1) error(0, "extra arguments for dump/list");
r = dmode(argc ? argv[0] : "-", mode, flags);
break;
case 's':
if (argc > 1) error(0, "extra argument(s) for stats");
r = smode(argc ? argv[0] : "-");
break;
default:
error(0, "no -q, -c, -d, -l or -s option specified");
}
if (r < 0 || fflush(stdout) < 0)
error(errno, "unable to write: %d", c);
return r;
}

64
tools/jso.c Normal file
View file

@ -0,0 +1,64 @@
#include <stdio.h>
#include <stdarg.h>
#include "quickjs.h"
#include <string.h>
#include <stdlib.h>
char *seprint(char *fmt, ...)
{
va_list args;
va_start (args, fmt);
char test[128];
int len = vsnprintf(test, 128, fmt, args);
if (len > 128) {
char test = malloc(len+1);
vsnprintf(test, len+1, fmt, args);
return test;
}
return strdup(test);
}
static JSContext *js = NULL;
static JSRuntime *rt = NULL;
int main (int argc, char **argv)
{
if (argc < 2) {
printf("Must supply with one or more javascript files.\n");
return 1;
}
rt = JS_NewRuntime();
JS_SetMaxStackSize(rt,0);
js = JS_NewContext(rt);
for (int i = 1; i < argc; i++) {
FILE *f = fopen(argv[i], "rb");
if (!f) {
printf("Could not find file %s.\n", argv[i]);
continue;
}
fseek(f,0,SEEK_END);
size_t fsize = ftell(f);
rewind(f);
void *script = malloc(fsize);
fread(script,fsize,1,f);
fclose(f);
JSValue obj = JS_Eval(js, script, fsize, argv[i], JS_EVAL_FLAG_COMPILE_ONLY | JS_EVAL_FLAG_STRICT);
size_t out_len;
uint8_t *out;
out = JS_WriteObject(js, &out_len, obj, JS_WRITE_OBJ_BYTECODE);
printf(out);
return 0;
char *out_name = seprint("%s.o", argv[i]);
FILE *fo = fopen(out_name, "wb");
fputs(out, fo);
fclose(fo);
}
return 0;
}

42
tools/packer.c Normal file
View file

@ -0,0 +1,42 @@
#include <string.h>
#include <stddef.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include "cdb.h"
static struct cdb_make cdbm;
/* Take all input files and zip them into a cdb */
int main(int argc, char **argv)
{
static int cmd = 0;
static char *file = "out.cdb";
int fd;
char *key, *va;
unsigned klen, vlen;
fd = open(file,O_RDWR|O_CREAT);
cdb_make_start(&cdbm, fd);
for (int i = 1; i < argc; i++) {
FILE *f;
char *file = argv[i];
f = fopen(file, "rb");
fseek(f,0,SEEK_END);
size_t fsize = ftell(f);
rewind(f);
void *slurp = malloc(fsize);
fread(slurp,fsize,1,f);
fclose(f);
cdb_make_add(&cdbm, file, strlen(file), slurp, fsize);
free(slurp);
}
cdb_make_finish(&cdbm);
return 0;
}