From ced3c6fc5cfdfcd9a94507d48afe1645c3f6366d Mon Sep 17 00:00:00 2001 From: Eric S Date: Sun, 23 Jul 2023 21:44:57 +0000 Subject: [PATCH] Add fcntl module --- Makefile | 6 ++- src/modules/module_fcntl.c | 99 ++++++++++++++++++++++++++++++++++++++ tools/gendoc.krk | 1 + 3 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 src/modules/module_fcntl.c diff --git a/Makefile b/Makefile index e413d8b..59db8a5 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ LDFLAGS += -L. TARGET = kuroko OBJS = $(patsubst %.c, %.o, $(filter-out src/kuroko.c,$(sort $(wildcard src/*.c)))) SOOBJS = $(patsubst %.o, %.lo, $(OBJS)) -MODULES = $(patsubst src/modules/module_%.c, modules/%.so, $(sort $(wildcard src/modules/module_*.c))) +MODULES = $(filter-out $(patsubst %, modules/%, $(EXCLUDED_MODULES)), $(patsubst src/modules/module_%.c, modules/%.so, $(sort $(wildcard src/modules/module_*.c)))) HEADERS = $(wildcard src/kuroko/*.h) TOOLS = $(patsubst tools/%.c, krk-%, $(sort $(wildcard tools/*.c))) GENMODS = modules/codecs/sbencs.krk modules/codecs/dbdata.krk @@ -19,7 +19,7 @@ VERSION = $(shell ./kuroko --version | sed 's/.* //') SONAME = libkuroko-$(VERSION).so KRKMODS = $(wildcard modules/*.krk modules/*/*.krk modules/*/*/*.krk) -all: ${TARGET} ${MODULES} ${TOOLS} ${GENMODS} +all: ${TARGET} ${TOOLS} ${GENMODS} ifneq ($(shell tools/can-floor-without-libm.sh $(CC)),yes) LDLIBS += -lm @@ -37,6 +37,7 @@ ifeq (,$(findstring mingw,$(CC))) endif else CFLAGS += -Wno-format -static-libgcc -pthread + EXCLUDED_MODULES = fcntl.so ${SOOBJS}: CFLAGS += -DKRKINLIB BIN_OBJS = LIBRARY = libkuroko.dll @@ -45,6 +46,7 @@ else MODLIBS += -lkuroko modules/socket.so: MODLIBS += -lws2_32 endif +all: ${MODULES} ifdef KRK_DISABLE_DOCS CFLAGS += -DKRK_NO_DOCUMENTATION -Wno-unused-value diff --git a/src/modules/module_fcntl.c b/src/modules/module_fcntl.c new file mode 100644 index 0000000..a063ac9 --- /dev/null +++ b/src/modules/module_fcntl.c @@ -0,0 +1,99 @@ +#include +#include + +#include +#include +#include + +KRK_Function(fcntl) { + KrkValue fd_value; + int cmd; + KrkValue arg_value = NONE_VAL(); + if (!krk_parseArgs("Vi|V", + (const char*[]){"fd","cmd","arg"}, + &fd_value, &cmd, &arg_value)) { + return NONE_VAL(); + } + int fd; + if (IS_INTEGER(fd_value)) { + fd = AS_INTEGER(fd_value); + } else if (IS_INSTANCE(fd_value)){ + krk_push(fd_value); + if (!krk_bindMethod(krk_getType(fd_value), S("fileno"))) { + return krk_runtimeError(KRK_EXC(typeError), + "no fileno() method on '%T'", fd_value); + } + KrkValue fileno = krk_callStack(0); + if (!IS_INTEGER(fileno)) { + return krk_runtimeError(KRK_EXC(typeError), + "fileno() returned non-integer '%T'", fileno); + } + fd = AS_INTEGER(fileno); + } else { + return krk_runtimeError(KRK_EXC(typeError), + "expected integer or object with fileno(), not '%T'", fileno); + } + intptr_t arg; + KrkValue arg_copy = NONE_VAL(); + if (IS_NONE(arg_value)) { + arg = 0; + } else if (IS_INTEGER(arg_value)) { + arg = AS_INTEGER(arg_value); + } else if (IS_BYTES(arg_value)) { + KrkBytes *bytes = AS_BYTES(arg_value); + KrkBytes *copy = krk_newBytes(bytes->length, bytes->bytes); + arg = (intptr_t)copy->bytes; + arg_copy = OBJECT_VAL(copy); + } else { + return krk_runtimeError(KRK_EXC(typeError), + "expected integer or bytes arg, not '%T'", arg_value); + } + int result; + do { + result = fcntl(fd, cmd, arg); + } while (result == EINTR); + if (result < 0) { + return krk_runtimeError(KRK_EXC(OSError), "%s", strerror(errno)); + } + if (IS_NONE(arg_value) || IS_INTEGER(arg_value)) { + return INTEGER_VAL(result); + } else { + return arg_copy; + } +} + +KrkValue krk_module_onload_fcntl(void) { + KrkInstance *module = krk_newInstance(KRK_BASE_CLASS(module)); + krk_push(OBJECT_VAL(module)); + + KRK_DOC(module, "@brief Provides access to file descriptor duplicate, query, modify, lock, and unlock operations."); + + KRK_DOC(BIND_FUNC(module,fcntl), + "@brief Duplicate, query, modify, lock or unlock descriptor @c fd depending on the value of @c cmd.\n" + "@arguments fd,cmd,arg=None\n\n" + "@p fd must be a file descriptor or an object with a @c fileno method. " + "@p cmd should be an integer value defined by the @c F options. " + "@p arg must be an integer value or bytes if present. " + "@returns @ref int or @ref bytes"); + +#define FCNTL_CONST(c) krk_attachNamedValue(&module->fields, #c, INTEGER_VAL(c)) + + FCNTL_CONST(F_DUPFD); + FCNTL_CONST(F_DUPFD_CLOEXEC); + FCNTL_CONST(F_GETFD); + FCNTL_CONST(F_SETFD); + FCNTL_CONST(F_GETFL); + FCNTL_CONST(F_SETFL); + FCNTL_CONST(F_GETOWN); + FCNTL_CONST(F_SETOWN); + FCNTL_CONST(F_GETLK); + FCNTL_CONST(F_SETLK); + FCNTL_CONST(F_SETLKW); + + FCNTL_CONST(FD_CLOEXEC); + FCNTL_CONST(F_RDLCK); + FCNTL_CONST(F_UNLCK); + FCNTL_CONST(F_WRLCK); + + return krk_pop(); +} diff --git a/tools/gendoc.krk b/tools/gendoc.krk index 02acfd1..496836b 100755 --- a/tools/gendoc.krk +++ b/tools/gendoc.krk @@ -115,6 +115,7 @@ let modules = [ 'collections', 'string', 'callgrind', + 'fcntl', # Other stuff 'tools.gendoc',