Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aefd962baf | |||
| 983f9b7393 | |||
| 13067902a8 | |||
| 345cd35f19 | |||
| c2b9571c2d | |||
| 3f7f216c92 | |||
| 70d50dda92 | |||
| 70e9ec2fc3 | |||
| 110b7ffca8 | |||
| 26fb19a7f5 | |||
| bcb1795218 | |||
| fb0d8adb8f | |||
| 2c4d27f915 | |||
| 96fb957991 | |||
| 0cbee45ad2 |
+85
-1
@@ -7,6 +7,84 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.1.3] - 2026-02-25
|
||||
|
||||
### Added
|
||||
- **Module Metadata**: Optional metadata support for modules
|
||||
- `stk_mod_name` - human-readable module name
|
||||
- `stk_mod_version` - semantic version string
|
||||
- `stk_mod_description` - module description
|
||||
- All three are optional, missing symbols are not errors
|
||||
- Metadata stored in tight-packed arrays with index mappings
|
||||
- Setter functions to override default symbol names before `stk_init()`
|
||||
|
||||
## [0.1.2] - 2026-02-15
|
||||
|
||||
### Fixed
|
||||
- **Windows**
|
||||
- Module reload now works correctly, idk how it was broken
|
||||
- Temp directory creation fixed
|
||||
- `.tmp` directory now hidden via FILE_ATTRIBUTE_HIDDEN
|
||||
- Test build fixed
|
||||
- Force cmd.exe shell in gmake.mk
|
||||
- Fix bash syntax errors when running build.bat
|
||||
- **All Platforms**: platform_mkdir now checks if directory exists before creating
|
||||
|
||||
## [0.1.1] - 2026-02-14
|
||||
|
||||
### Fixed
|
||||
- **Logging**: Corrected log level severity order in enum
|
||||
- Reversed order so DEBUG (0) < INFO (1) < WARN (2) < ERROR (3)
|
||||
- Fixes filtering logic where ERROR/WARN were incorrectly blocked
|
||||
- Default INFO level now properly shows INFO, WARN, and ERROR while filtering DEBUG
|
||||
|
||||
## [0.1.0] - 2026-02-14
|
||||
|
||||
### Fixed
|
||||
- **C89 Compliance**: Removed stdint.h dependency (C99 feature)
|
||||
- Replaced all uint8_t with unsigned char throughout codebase
|
||||
- Ensures strict C89 compliance for maximum portability
|
||||
|
||||
### Added
|
||||
- **Flags system**: Centralized bitfield for boolean state and settings
|
||||
- Replaces stk_initialized with stk_flags for efficient memory usage
|
||||
- Single byte packs all boolean flags (STK_FLAG_INITIALIZED, STK_FLAG_LOGGING_ENABLED)
|
||||
- Runtime-changeable logging control via stk_set_logging_enabled()
|
||||
|
||||
- **Enhanced logging system**: Complete rewrite with modern features
|
||||
- Log levels: ERROR, WARN, INFO, DEBUG with runtime filtering
|
||||
- Timestamps: yyyy-mm-dd HH:MM:SS.mmm format (platform-specific implementation)
|
||||
- Configurable log output stream (stk_set_log_output)
|
||||
- Configurable log prefix (stk_set_log_prefix, defaults to "stk")
|
||||
- Configurable minimum log level (stk_set_log_level, defaults to INFO)
|
||||
- Platform abstraction for timestamps (GetLocalTime on Windows, gettimeofday on POSIX)
|
||||
|
||||
### Changed
|
||||
- **BREAKING**: stk_log() signature changed from stk_log(FILE *fp, ...) to stk_log(stk_log_level_t level, ...)
|
||||
- **BREAKING**: All uint8_t types replaced with unsigned char
|
||||
- All internal STK messages now use appropriate log levels
|
||||
- Setting log output to NULL disabls logging
|
||||
|
||||
### Notes
|
||||
- This release completes Phase 1 logging improvements
|
||||
- Dependency management still in progress for Phase 1 completion
|
||||
|
||||
## [0.0.4] - 2026-02-11
|
||||
|
||||
### Fixed
|
||||
- **Linux**: Fixed segfault from invalid module indices during extremely rapid file changes
|
||||
- Added validation check to skip stale UNLOAD/RELOAD events for already-unloaded modules
|
||||
- Prevents is_mod_loaded() returning -1 from being used as array index (SIZE_MAX)
|
||||
- Fixed event count mismatch where loops would run more iterations than valid indices populated
|
||||
- Completes the Linux hot-reload stability fixes from v0.0.2
|
||||
|
||||
## [0.0.3] - 2026-02-10
|
||||
|
||||
### Fixed
|
||||
- **Compilation**: Fixed GCC `-Wrestrict` warning in Linux directory watching code by replacing `strncpy` with `memmove` for overlapping memory operations
|
||||
- Ensures clean compilation without warnings while maintaining identical runtime behavior
|
||||
- Uses semantically correct function for moving memory within the same buffer
|
||||
|
||||
## [0.0.2] - 2026-02-09
|
||||
|
||||
### Fixed
|
||||
@@ -37,6 +115,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Dependency management and versioning not yet implemented
|
||||
- API is unstable and subject to change in future releases
|
||||
|
||||
[Unreleased]: https://github.com/anth64/stk/compare/v0.0.2...HEAD
|
||||
[Unreleased]: https://github.com/anth64/stk/compare/v0.1.2...HEAD
|
||||
[0.1.2]: https://github.com/anth64/stk/releases/tag/v0.1.2
|
||||
[0.1.1]: https://github.com/anth64/stk/releases/tag/v0.1.1
|
||||
[0.1.1]: https://github.com/anth64/stk/releases/tag/v0.1.1
|
||||
[0.1.0]: https://github.com/anth64/stk/releases/tag/v0.1.0
|
||||
[0.0.4]: https://github.com/anth64/stk/releases/tag/v0.0.4
|
||||
[0.0.3]: https://github.com/anth64/stk/releases/tag/v0.0.3
|
||||
[0.0.2]: https://github.com/anth64/stk/releases/tag/v0.0.2
|
||||
[0.0.1]: https://github.com/anth64/stk/releases/tag/v0.0.1
|
||||
|
||||
@@ -146,6 +146,15 @@ stk_set_module_init_fn("my_init");
|
||||
/* Set custom shutdown function name (default: "stk_mod_shutdown") */
|
||||
stk_set_module_shutdown_fn("my_shutdown");
|
||||
|
||||
/* Set function name to get module name */
|
||||
stk_set_module_name_fn("my_mod_name");
|
||||
|
||||
/* Set function name to get module version */
|
||||
stk_set_module_version_fn("my_mod_version");
|
||||
|
||||
/* Set functio name to get module description */
|
||||
stk_set_module_description_fn("my_mod_description");
|
||||
|
||||
/*
|
||||
* All the above functions must be called before stk_init()
|
||||
* if the defaults need to be changed.
|
||||
@@ -156,7 +165,7 @@ stk_init();
|
||||
### API Reference
|
||||
|
||||
#### Initialization
|
||||
- `uint8_t stk_init(void)` - Initialize stk, returns `STK_INIT_SUCCESS` on success
|
||||
- `unsigned char stk_init(void)` - Initialize stk, returns `STK_INIT_SUCCESS` on success
|
||||
- `void stk_shutdown(void)` - Shutdown and cleanup all modules
|
||||
|
||||
#### Runtime
|
||||
@@ -169,22 +178,31 @@ stk_init();
|
||||
- `void stk_set_module_init_fn(const char *name)` - Set module init function name
|
||||
- `void stk_set_module_shutdown_fn(const char *name)` - Set module shutdown function name
|
||||
|
||||
#### Logging
|
||||
- `void stk_set_logging_enabled(unsigned char enabled)` - Enable/disable all logging
|
||||
- `unsigned char stk_is_logging_enabled(void)` - Query logging state
|
||||
- `void stk_set_log_output(FILE *fp)` - Set log output stream (default: stdout, NULL disables)
|
||||
- `void stk_set_log_prefix(const char *prefix)` - Set log prefix (default: "stk")
|
||||
- `void stk_set_log_level(stk_log_level_t level)` - Set minimum log level (default: INFO)
|
||||
|
||||
**Log Levels:** `STK_LOG_ERROR`, `STK_LOG_WARN`, `STK_LOG_INFO`, `STK_LOG_DEBUG`
|
||||
|
||||
---
|
||||
|
||||
## Project Status
|
||||
|
||||
**Current Version:** 0.0.2 (Pre-release)
|
||||
**Current Version:** 0.1.2 (Pre-release)
|
||||
|
||||
This is an early bugfix release improving hot-reload stability on Linux. Phase 1 is still in progress.
|
||||
Fixed Windows compatibility issues.
|
||||
|
||||
### What Works
|
||||
- Cross-platform module loading and hot-reloading
|
||||
- File watching (inotify/kqueue/FindFirstFile)
|
||||
- Basic error handling
|
||||
- Stable hot-reload even during rapid file changes (Linux fix in 0.0.2)
|
||||
- Robust hot-reload even during extremely rapid file changes
|
||||
- Enhanced logging with levels, timestamps, and filtering
|
||||
- Runtime-configurable logging behavior
|
||||
|
||||
### In Progress (Phase 1)
|
||||
- Complete logging system (log levels, verbosity, output configuration)
|
||||
- Module metadata (name, version, description)
|
||||
- Dependency management and versioning
|
||||
|
||||
|
||||
+14
-2
@@ -2,12 +2,15 @@
|
||||
#define STK_H
|
||||
|
||||
#include "stk_version.h"
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Buffers */
|
||||
#define STK_LOG_PREFIX_BUFFER 64
|
||||
#define STK_MOD_DESC_BUFFER 256
|
||||
#define STK_MOD_DIR_BUFFER 256
|
||||
#define STK_MOD_ID_BUFFER 64
|
||||
#define STK_MOD_NAME_BUFFER 128
|
||||
#define STK_MOD_VERSION_BUFFER 32
|
||||
#define STK_PATH_MAX 256
|
||||
#define STK_PATH_MAX_OS 4096
|
||||
|
||||
@@ -31,6 +34,10 @@
|
||||
#define STK_PLATFORM_REMOVE_DIR_ERROR 3
|
||||
#define STK_PLATFORM_REMOVE_FILE_ERROR 4
|
||||
|
||||
/* Settings flags */
|
||||
#define STK_FLAG_INITIALIZED 0x01
|
||||
#define STK_FLAG_LOGGING_ENABLED 0x02
|
||||
|
||||
#if defined(__linux__) || defined(_WIN32)
|
||||
#define STK_EVENT_BUFFER 4096
|
||||
#endif
|
||||
@@ -55,7 +62,7 @@ typedef enum {
|
||||
STK_MOD_RELOAD
|
||||
} stk_module_event_t;
|
||||
|
||||
uint8_t stk_init(void);
|
||||
unsigned char stk_init(void);
|
||||
void stk_shutdown(void);
|
||||
size_t stk_module_count(void);
|
||||
size_t stk_poll(void);
|
||||
@@ -63,6 +70,11 @@ void stk_set_mod_dir(const char *path);
|
||||
void stk_set_tmp_dir_name(const char *name);
|
||||
void stk_set_module_init_fn(const char *name);
|
||||
void stk_set_module_shutdown_fn(const char *name);
|
||||
void stk_set_logging_enabled(unsigned char enabled);
|
||||
void stk_set_module_name_fn(const char *name);
|
||||
void stk_set_module_version_fn(const char *name);
|
||||
void stk_set_module_description_fn(const char *name);
|
||||
unsigned char stk_is_logging_enabled(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
+12
-1
@@ -7,7 +7,18 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void stk_log(FILE *fp, const char *fmt, ...);
|
||||
typedef enum {
|
||||
STK_LOG_DEBUG,
|
||||
STK_LOG_INFO,
|
||||
STK_LOG_WARN,
|
||||
STK_LOG_ERROR
|
||||
} stk_log_level_t;
|
||||
|
||||
void stk_set_log_output(FILE *fp);
|
||||
void stk_set_log_prefix(const char *prefix);
|
||||
void stk_set_log_level(stk_log_level_t min_level);
|
||||
|
||||
void stk_log(stk_log_level_t level, const char *fmt, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#define STK_VERSION_H
|
||||
|
||||
#define STK_VERSION_MAJOR 0
|
||||
#define STK_VERSION_MINOR 0
|
||||
#define STK_VERSION_PATCH 2
|
||||
#define STK_VERSION_MINOR 1
|
||||
#define STK_VERSION_PATCH 3
|
||||
|
||||
#define STK_STRINGIFY_HELPER(x) #x
|
||||
#define STK_STRINGIFY(x) STK_STRINGIFY_HELPER(x)
|
||||
|
||||
+346
-13
@@ -1,6 +1,5 @@
|
||||
#include "platform.h"
|
||||
#include "stk.h"
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -18,11 +17,26 @@ void **stk_handles = NULL;
|
||||
stk_init_mod_func *stk_inits = NULL;
|
||||
stk_shutdown_mod_func *stk_shutdowns = NULL;
|
||||
|
||||
extern uint8_t stk_initialized;
|
||||
char (*stk_meta_names)[STK_MOD_NAME_BUFFER] = NULL;
|
||||
size_t *stk_meta_name_indices = NULL;
|
||||
size_t stk_meta_name_count = 0;
|
||||
|
||||
char (*stk_meta_versions)[STK_MOD_VERSION_BUFFER] = NULL;
|
||||
size_t *stk_meta_version_indices = NULL;
|
||||
size_t stk_meta_version_count = 0;
|
||||
|
||||
char (*stk_meta_descs)[STK_MOD_DESC_BUFFER] = NULL;
|
||||
size_t *stk_meta_desc_indices = NULL;
|
||||
size_t stk_meta_desc_count = 0;
|
||||
|
||||
extern unsigned char stk_flags;
|
||||
|
||||
static char stk_mod_init_name[STK_MOD_FUNC_NAME_BUFFER] = "stk_mod_init";
|
||||
static char stk_mod_shutdown_name[STK_MOD_FUNC_NAME_BUFFER] =
|
||||
"stk_mod_shutdown";
|
||||
static char stk_mod_name_fn[STK_MOD_NAME_BUFFER] = "stk_mod_name";
|
||||
static char stk_mod_version_fn[STK_MOD_VERSION_BUFFER] = "stk_mod_version";
|
||||
static char stk_mod_description_fn[STK_MOD_DESC_BUFFER] = "stk_mod_description";
|
||||
|
||||
size_t module_count = 0;
|
||||
|
||||
@@ -43,7 +57,7 @@ void extract_module_id(const char *path, char *out_id)
|
||||
*dot = '\0';
|
||||
}
|
||||
|
||||
uint8_t is_valid_module_file(const char *filename)
|
||||
unsigned char is_valid_module_file(const char *filename)
|
||||
{
|
||||
const char *ext;
|
||||
size_t name_len;
|
||||
@@ -72,7 +86,7 @@ int is_mod_loaded(const char *module_name)
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t stk_module_load(const char *path, int index)
|
||||
unsigned char stk_module_load(const char *path, int index)
|
||||
{
|
||||
void *handle;
|
||||
stk_init_mod_func init_func;
|
||||
@@ -82,8 +96,17 @@ uint8_t stk_module_load(const char *path, int index)
|
||||
void *obj;
|
||||
stk_init_mod_func init_func;
|
||||
stk_shutdown_mod_func shutdown_func;
|
||||
const char *(*meta_func)(void);
|
||||
} u;
|
||||
size_t len;
|
||||
const char *meta_str;
|
||||
|
||||
char (*new_meta_names)[STK_MOD_NAME_BUFFER] = NULL;
|
||||
size_t *new_meta_name_indices = NULL;
|
||||
char (*new_meta_versions)[STK_MOD_VERSION_BUFFER] = NULL;
|
||||
size_t *new_meta_version_indices = NULL;
|
||||
char (*new_meta_descs)[STK_MOD_DESC_BUFFER] = NULL;
|
||||
size_t *new_meta_desc_indices = NULL;
|
||||
|
||||
handle = platform_load_library(path);
|
||||
if (!handle)
|
||||
@@ -118,10 +141,83 @@ uint8_t stk_module_load(const char *path, int index)
|
||||
stk_inits[index] = init_func;
|
||||
stk_shutdowns[index] = shutdown_func;
|
||||
|
||||
u.obj = platform_get_symbol(handle, stk_mod_name_fn);
|
||||
if (!u.obj)
|
||||
goto skip_name;
|
||||
meta_str = u.meta_func();
|
||||
if (!meta_str)
|
||||
goto skip_name;
|
||||
|
||||
new_meta_names = realloc(stk_meta_names, (stk_meta_name_count + 1) *
|
||||
sizeof(*stk_meta_names));
|
||||
new_meta_name_indices = realloc(
|
||||
stk_meta_name_indices, (stk_meta_name_count + 1) * sizeof(size_t));
|
||||
if (!new_meta_names || !new_meta_name_indices)
|
||||
goto skip_name;
|
||||
|
||||
stk_meta_names = new_meta_names;
|
||||
stk_meta_name_indices = new_meta_name_indices;
|
||||
strncpy(stk_meta_names[stk_meta_name_count], meta_str,
|
||||
STK_MOD_NAME_BUFFER - 1);
|
||||
stk_meta_names[stk_meta_name_count][STK_MOD_NAME_BUFFER - 1] = '\0';
|
||||
stk_meta_name_indices[stk_meta_name_count] = (size_t)index;
|
||||
stk_meta_name_count++;
|
||||
|
||||
skip_name:
|
||||
u.obj = platform_get_symbol(handle, stk_mod_version_fn);
|
||||
if (!u.obj)
|
||||
goto skip_version;
|
||||
|
||||
meta_str = u.meta_func();
|
||||
if (!meta_str)
|
||||
goto skip_version;
|
||||
|
||||
new_meta_versions =
|
||||
realloc(stk_meta_versions,
|
||||
(stk_meta_version_count + 1) * sizeof(*stk_meta_versions));
|
||||
new_meta_version_indices =
|
||||
realloc(stk_meta_version_indices,
|
||||
(stk_meta_version_count + 1) * sizeof(size_t));
|
||||
if (!new_meta_versions || !new_meta_version_indices)
|
||||
goto skip_version;
|
||||
|
||||
stk_meta_versions = new_meta_versions;
|
||||
stk_meta_version_indices = new_meta_version_indices;
|
||||
strncpy(stk_meta_versions[stk_meta_version_count], meta_str,
|
||||
STK_MOD_VERSION_BUFFER - 1);
|
||||
stk_meta_versions[stk_meta_version_count][STK_MOD_VERSION_BUFFER - 1] =
|
||||
'\0';
|
||||
stk_meta_version_indices[stk_meta_version_count] = (size_t)index;
|
||||
stk_meta_version_count++;
|
||||
|
||||
skip_version:
|
||||
u.obj = platform_get_symbol(handle, stk_mod_description_fn);
|
||||
if (!u.obj)
|
||||
goto skip_description;
|
||||
|
||||
meta_str = u.meta_func();
|
||||
if (!meta_str)
|
||||
goto skip_description;
|
||||
|
||||
new_meta_descs = realloc(stk_meta_descs, (stk_meta_desc_count + 1) *
|
||||
sizeof(*stk_meta_descs));
|
||||
new_meta_desc_indices = realloc(
|
||||
stk_meta_desc_indices, (stk_meta_desc_count + 1) * sizeof(size_t));
|
||||
if (!new_meta_descs || !new_meta_desc_indices)
|
||||
goto skip_description;
|
||||
stk_meta_descs = new_meta_descs;
|
||||
stk_meta_desc_indices = new_meta_desc_indices;
|
||||
strncpy(stk_meta_descs[stk_meta_desc_count], meta_str,
|
||||
STK_MOD_DESC_BUFFER - 1);
|
||||
stk_meta_descs[stk_meta_desc_count][STK_MOD_DESC_BUFFER - 1] = '\0';
|
||||
stk_meta_desc_indices[stk_meta_desc_count] = (size_t)index;
|
||||
stk_meta_desc_count++;
|
||||
|
||||
skip_description:
|
||||
return STK_MOD_INIT_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t stk_module_load_init(const char *path, int index)
|
||||
unsigned char stk_module_load_init(const char *path, int index)
|
||||
{
|
||||
int result;
|
||||
result = stk_module_load(path, index);
|
||||
@@ -134,12 +230,112 @@ uint8_t stk_module_load_init(const char *path, int index)
|
||||
|
||||
void stk_module_unload(size_t index)
|
||||
{
|
||||
size_t i;
|
||||
char (*new_meta_names)[STK_MOD_NAME_BUFFER] = NULL;
|
||||
size_t *new_meta_name_indices = NULL;
|
||||
char (*new_meta_versions)[STK_MOD_VERSION_BUFFER] = NULL;
|
||||
size_t *new_meta_version_indices = NULL;
|
||||
char (*new_meta_descs)[STK_MOD_DESC_BUFFER] = NULL;
|
||||
size_t *new_meta_desc_indices = NULL;
|
||||
size_t new_count;
|
||||
|
||||
stk_shutdowns[index]();
|
||||
platform_unload_library(stk_handles[index]);
|
||||
stk_handles[index] = NULL;
|
||||
stk_inits[index] = NULL;
|
||||
stk_shutdowns[index] = NULL;
|
||||
stk_module_ids[index][0] = '\0';
|
||||
|
||||
new_count = 0;
|
||||
for (i = 0; i < stk_meta_name_count; i++)
|
||||
if (stk_meta_name_indices[i] != index)
|
||||
new_count++;
|
||||
|
||||
if (new_count == 0)
|
||||
goto clear_names;
|
||||
|
||||
new_meta_names = malloc(new_count * sizeof(*new_meta_names));
|
||||
new_meta_name_indices = malloc(new_count * sizeof(size_t));
|
||||
if (!new_meta_names || !new_meta_name_indices)
|
||||
goto clear_names;
|
||||
|
||||
new_count = 0;
|
||||
for (i = 0; i < stk_meta_name_count; i++) {
|
||||
if (stk_meta_name_indices[i] == index)
|
||||
continue;
|
||||
memcpy(new_meta_names[new_count], stk_meta_names[i],
|
||||
STK_MOD_NAME_BUFFER);
|
||||
new_meta_name_indices[new_count] = stk_meta_name_indices[i];
|
||||
new_count++;
|
||||
}
|
||||
|
||||
clear_names:
|
||||
free(stk_meta_names);
|
||||
free(stk_meta_name_indices);
|
||||
stk_meta_names = new_meta_names;
|
||||
stk_meta_name_indices = new_meta_name_indices;
|
||||
stk_meta_name_count = new_count;
|
||||
|
||||
new_count = 0;
|
||||
for (i = 0; i < stk_meta_version_count; i++)
|
||||
if (stk_meta_version_indices[i] != index)
|
||||
new_count++;
|
||||
|
||||
if (new_count == 0)
|
||||
goto clear_versions;
|
||||
|
||||
new_meta_versions = malloc(new_count * sizeof(*new_meta_versions));
|
||||
new_meta_version_indices = malloc(new_count * sizeof(size_t));
|
||||
if (!new_meta_versions || !new_meta_version_indices)
|
||||
goto clear_versions;
|
||||
|
||||
new_count = 0;
|
||||
for (i = 0; i < stk_meta_version_count; i++) {
|
||||
if (stk_meta_version_indices[i] == index)
|
||||
continue;
|
||||
memcpy(new_meta_versions[new_count], stk_meta_versions[i],
|
||||
STK_MOD_VERSION_BUFFER);
|
||||
new_meta_version_indices[new_count] =
|
||||
stk_meta_version_indices[i];
|
||||
new_count++;
|
||||
}
|
||||
|
||||
clear_versions:
|
||||
free(stk_meta_versions);
|
||||
free(stk_meta_version_indices);
|
||||
stk_meta_versions = new_meta_versions;
|
||||
stk_meta_version_indices = new_meta_version_indices;
|
||||
stk_meta_version_count = new_count;
|
||||
|
||||
new_count = 0;
|
||||
for (i = 0; i < stk_meta_desc_count; i++)
|
||||
if (stk_meta_desc_indices[i] != index)
|
||||
new_count++;
|
||||
|
||||
if (new_count == 0)
|
||||
goto clear_descs;
|
||||
|
||||
new_meta_descs = malloc(new_count * sizeof(*new_meta_descs));
|
||||
new_meta_desc_indices = malloc(new_count * sizeof(size_t));
|
||||
if (!new_meta_descs || !new_meta_desc_indices)
|
||||
goto clear_descs;
|
||||
|
||||
new_count = 0;
|
||||
for (i = 0; i < stk_meta_desc_count; i++) {
|
||||
if (stk_meta_desc_indices[i] == index)
|
||||
continue;
|
||||
memcpy(new_meta_descs[new_count], stk_meta_descs[i],
|
||||
STK_MOD_DESC_BUFFER);
|
||||
new_meta_desc_indices[new_count] = stk_meta_desc_indices[i];
|
||||
new_count++;
|
||||
}
|
||||
|
||||
clear_descs:
|
||||
free(stk_meta_descs);
|
||||
free(stk_meta_desc_indices);
|
||||
stk_meta_descs = new_meta_descs;
|
||||
stk_meta_desc_indices = new_meta_desc_indices;
|
||||
stk_meta_desc_count = new_count;
|
||||
}
|
||||
|
||||
void stk_module_free_memory(void)
|
||||
@@ -153,9 +349,26 @@ void stk_module_free_memory(void)
|
||||
stk_handles = NULL;
|
||||
stk_inits = NULL;
|
||||
stk_shutdowns = NULL;
|
||||
|
||||
free(stk_meta_names);
|
||||
free(stk_meta_name_indices);
|
||||
free(stk_meta_versions);
|
||||
free(stk_meta_version_indices);
|
||||
free(stk_meta_descs);
|
||||
free(stk_meta_desc_indices);
|
||||
|
||||
stk_meta_names = NULL;
|
||||
stk_meta_name_indices = NULL;
|
||||
stk_meta_name_count = 0;
|
||||
stk_meta_versions = NULL;
|
||||
stk_meta_version_indices = NULL;
|
||||
stk_meta_version_count = 0;
|
||||
stk_meta_descs = NULL;
|
||||
stk_meta_desc_indices = NULL;
|
||||
stk_meta_desc_count = 0;
|
||||
}
|
||||
|
||||
uint8_t stk_module_init_memory(size_t capacity)
|
||||
unsigned char stk_module_init_memory(size_t capacity)
|
||||
{
|
||||
stk_module_ids = malloc(capacity * sizeof(*stk_module_ids));
|
||||
stk_handles = malloc(capacity * sizeof(void *));
|
||||
@@ -167,15 +380,31 @@ uint8_t stk_module_init_memory(size_t capacity)
|
||||
return STK_INIT_MEMORY_ERROR;
|
||||
}
|
||||
|
||||
stk_meta_names = NULL;
|
||||
stk_meta_name_indices = NULL;
|
||||
stk_meta_name_count = 0;
|
||||
stk_meta_versions = NULL;
|
||||
stk_meta_version_indices = NULL;
|
||||
stk_meta_version_count = 0;
|
||||
stk_meta_descs = NULL;
|
||||
stk_meta_desc_indices = NULL;
|
||||
stk_meta_desc_count = 0;
|
||||
|
||||
return STK_INIT_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t stk_module_realloc_memory(size_t new_capacity)
|
||||
unsigned char stk_module_realloc_memory(size_t new_capacity)
|
||||
{
|
||||
char (*new_module_ids)[STK_MOD_ID_BUFFER] = NULL;
|
||||
void **new_handles = NULL;
|
||||
stk_init_mod_func *new_inits = NULL;
|
||||
stk_shutdown_mod_func *new_shutdowns = NULL;
|
||||
char (*new_meta_names)[STK_MOD_NAME_BUFFER] = NULL;
|
||||
size_t *new_meta_name_indices = NULL;
|
||||
char (*new_meta_versions)[STK_MOD_VERSION_BUFFER] = NULL;
|
||||
size_t *new_meta_version_indices = NULL;
|
||||
char (*new_meta_descs)[STK_MOD_DESC_BUFFER] = NULL;
|
||||
size_t *new_meta_desc_indices = NULL;
|
||||
size_t i, copy_count;
|
||||
|
||||
if (new_capacity == 0) {
|
||||
@@ -191,16 +420,12 @@ uint8_t stk_module_realloc_memory(size_t new_capacity)
|
||||
if (!new_module_ids || !new_handles || !new_inits || !new_shutdowns) {
|
||||
if (new_module_ids)
|
||||
free(new_module_ids);
|
||||
|
||||
if (new_handles)
|
||||
free(new_handles);
|
||||
|
||||
if (new_inits)
|
||||
free(new_inits);
|
||||
|
||||
if (new_shutdowns)
|
||||
free(new_shutdowns);
|
||||
|
||||
return STK_MOD_REALLOC_FAILURE;
|
||||
}
|
||||
|
||||
@@ -233,6 +458,80 @@ uint8_t stk_module_realloc_memory(size_t new_capacity)
|
||||
new_shutdowns[i] = NULL;
|
||||
}
|
||||
|
||||
if (stk_meta_name_count == 0)
|
||||
goto skip_meta_names;
|
||||
|
||||
new_meta_names = malloc(stk_meta_name_count * sizeof(*stk_meta_names));
|
||||
new_meta_name_indices = malloc(stk_meta_name_count * sizeof(size_t));
|
||||
if (!new_meta_names || !new_meta_name_indices) {
|
||||
if (new_meta_names)
|
||||
free(new_meta_names);
|
||||
|
||||
if (new_meta_name_indices)
|
||||
free(new_meta_name_indices);
|
||||
|
||||
new_meta_names = NULL;
|
||||
new_meta_name_indices = NULL;
|
||||
goto skip_meta_names;
|
||||
}
|
||||
|
||||
for (i = 0; i < stk_meta_name_count; i++) {
|
||||
strncpy(new_meta_names[i], stk_meta_names[i],
|
||||
STK_MOD_NAME_BUFFER - 1);
|
||||
new_meta_names[i][STK_MOD_NAME_BUFFER - 1] = '\0';
|
||||
new_meta_name_indices[i] = stk_meta_name_indices[i];
|
||||
}
|
||||
|
||||
skip_meta_names:
|
||||
if (stk_meta_version_count == 0)
|
||||
goto skip_meta_versions;
|
||||
|
||||
new_meta_versions =
|
||||
malloc(stk_meta_version_count * sizeof(*stk_meta_versions));
|
||||
new_meta_version_indices =
|
||||
malloc(stk_meta_version_count * sizeof(size_t));
|
||||
if (!new_meta_versions || !new_meta_version_indices) {
|
||||
if (new_meta_versions)
|
||||
free(new_meta_versions);
|
||||
if (new_meta_version_indices)
|
||||
free(new_meta_version_indices);
|
||||
new_meta_versions = NULL;
|
||||
new_meta_version_indices = NULL;
|
||||
goto skip_meta_versions;
|
||||
}
|
||||
|
||||
for (i = 0; i < stk_meta_version_count; i++) {
|
||||
strncpy(new_meta_versions[i], stk_meta_versions[i],
|
||||
STK_MOD_VERSION_BUFFER - 1);
|
||||
new_meta_versions[i][STK_MOD_VERSION_BUFFER - 1] = '\0';
|
||||
new_meta_version_indices[i] = stk_meta_version_indices[i];
|
||||
}
|
||||
|
||||
skip_meta_versions:
|
||||
if (stk_meta_desc_count == 0)
|
||||
goto skip_meta_descs;
|
||||
|
||||
new_meta_descs = malloc(stk_meta_desc_count * sizeof(*stk_meta_descs));
|
||||
new_meta_desc_indices = malloc(stk_meta_desc_count * sizeof(size_t));
|
||||
if (!new_meta_descs || !new_meta_desc_indices) {
|
||||
if (new_meta_descs)
|
||||
free(new_meta_descs);
|
||||
if (new_meta_desc_indices)
|
||||
free(new_meta_desc_indices);
|
||||
new_meta_descs = NULL;
|
||||
new_meta_desc_indices = NULL;
|
||||
goto skip_meta_descs;
|
||||
}
|
||||
|
||||
for (i = 0; i < stk_meta_desc_count; i++) {
|
||||
strncpy(new_meta_descs[i], stk_meta_descs[i],
|
||||
STK_MOD_DESC_BUFFER - 1);
|
||||
new_meta_descs[i][STK_MOD_DESC_BUFFER - 1] = '\0';
|
||||
new_meta_desc_indices[i] = stk_meta_desc_indices[i];
|
||||
}
|
||||
|
||||
skip_meta_descs:
|
||||
|
||||
stk_module_free_memory();
|
||||
|
||||
stk_module_ids = new_module_ids;
|
||||
@@ -240,6 +539,13 @@ uint8_t stk_module_realloc_memory(size_t new_capacity)
|
||||
stk_inits = new_inits;
|
||||
stk_shutdowns = new_shutdowns;
|
||||
|
||||
stk_meta_names = new_meta_names;
|
||||
stk_meta_name_indices = new_meta_name_indices;
|
||||
stk_meta_versions = new_meta_versions;
|
||||
stk_meta_version_indices = new_meta_version_indices;
|
||||
stk_meta_descs = new_meta_descs;
|
||||
stk_meta_desc_indices = new_meta_desc_indices;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -254,7 +560,7 @@ void stk_module_unload_all(void)
|
||||
|
||||
void stk_set_module_init_fn(const char *name)
|
||||
{
|
||||
if (!name || stk_initialized)
|
||||
if (!name || (stk_flags & STK_FLAG_INITIALIZED))
|
||||
return;
|
||||
|
||||
strncpy(stk_mod_init_name, name, STK_MOD_FUNC_NAME_BUFFER - 1);
|
||||
@@ -263,9 +569,36 @@ void stk_set_module_init_fn(const char *name)
|
||||
|
||||
void stk_set_module_shutdown_fn(const char *name)
|
||||
{
|
||||
if (!name || stk_initialized)
|
||||
if (!name || (stk_flags & STK_FLAG_INITIALIZED))
|
||||
return;
|
||||
|
||||
strncpy(stk_mod_shutdown_name, name, STK_MOD_FUNC_NAME_BUFFER - 1);
|
||||
stk_mod_shutdown_name[STK_MOD_FUNC_NAME_BUFFER - 1] = '\0';
|
||||
}
|
||||
|
||||
void stk_set_module_name_fn(const char *name)
|
||||
{
|
||||
if (!name || (stk_flags & STK_FLAG_INITIALIZED))
|
||||
return;
|
||||
|
||||
strncpy(stk_mod_name_fn, name, STK_MOD_NAME_BUFFER - 1);
|
||||
stk_mod_name_fn[STK_MOD_NAME_BUFFER - 1] = '\0';
|
||||
}
|
||||
|
||||
void stk_set_module_version_fn(const char *name)
|
||||
{
|
||||
if (!name || (stk_flags & STK_FLAG_INITIALIZED))
|
||||
return;
|
||||
|
||||
strncpy(stk_mod_version_fn, name, STK_MOD_VERSION_BUFFER - 1);
|
||||
stk_mod_version_fn[STK_MOD_VERSION_BUFFER - 1] = '\0';
|
||||
}
|
||||
|
||||
void stk_set_module_description_fn(const char *name)
|
||||
{
|
||||
if (!name || (stk_flags & STK_FLAG_INITIALIZED))
|
||||
return;
|
||||
|
||||
strncpy(stk_mod_description_fn, name, STK_MOD_DESC_BUFFER - 1);
|
||||
stk_mod_description_fn[STK_MOD_DESC_BUFFER - 1] = '\0';
|
||||
}
|
||||
|
||||
+63
-27
@@ -1,38 +1,34 @@
|
||||
#include "stk.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <dirent.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <dirent.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#elif defined(_WIN32)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
int is_mod_loaded(const char *module_name);
|
||||
uint8_t is_valid_module_file(const char *filename);
|
||||
unsigned char is_valid_module_file(const char *filename);
|
||||
void extract_module_id(const char *path, char *out_id);
|
||||
|
||||
static uint8_t is_file_ready(const char *dir_path, const char *filename)
|
||||
static unsigned char is_file_ready(const char *dir_path, const char *filename)
|
||||
{
|
||||
char full_path[STK_PATH_MAX_OS];
|
||||
#ifdef _WIN32
|
||||
@@ -108,12 +104,32 @@ typedef struct {
|
||||
} platform_watch_context_t;
|
||||
#endif
|
||||
|
||||
uint8_t platform_mkdir(const char *path)
|
||||
unsigned char platform_mkdir(const char *path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return CreateDirectoryA(path, NULL) ? STK_PLATFORM_OPERATION_SUCCESS
|
||||
: STK_PLATFORM_MKDIR_ERROR;
|
||||
DWORD attrib;
|
||||
|
||||
attrib = GetFileAttributesA(path);
|
||||
|
||||
if (attrib != INVALID_FILE_ATTRIBUTES &&
|
||||
(attrib & FILE_ATTRIBUTE_DIRECTORY))
|
||||
return STK_PLATFORM_OPERATION_SUCCESS;
|
||||
|
||||
if (!CreateDirectoryA(path, NULL))
|
||||
return STK_PLATFORM_MKDIR_ERROR;
|
||||
|
||||
if (strrchr(path, '\\') && *(strrchr(path, '\\') + 1) == '.')
|
||||
SetFileAttributesA(path, FILE_ATTRIBUTE_HIDDEN);
|
||||
else if (!strrchr(path, '\\') && path[0] == '.')
|
||||
SetFileAttributesA(path, FILE_ATTRIBUTE_HIDDEN);
|
||||
|
||||
return STK_PLATFORM_OPERATION_SUCCESS;
|
||||
#else
|
||||
struct stat st;
|
||||
|
||||
if (stat(path, &st) == 0 && S_ISDIR(st.st_mode))
|
||||
return STK_PLATFORM_OPERATION_SUCCESS;
|
||||
|
||||
return mkdir(path, 0755) == 0 ? STK_PLATFORM_OPERATION_SUCCESS
|
||||
: STK_PLATFORM_MKDIR_ERROR;
|
||||
#endif
|
||||
@@ -130,7 +146,7 @@ int platform_remove_file(const char *path)
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t platform_copy_file(const char *from, const char *to)
|
||||
unsigned char platform_copy_file(const char *from, const char *to)
|
||||
{
|
||||
char buf[STK_PATH_MAX_OS];
|
||||
int ret = STK_PLATFORM_FILE_COPY_ERROR;
|
||||
@@ -203,7 +219,7 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t platform_remove_dir(const char *path)
|
||||
unsigned char platform_remove_dir(const char *path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WIN32_FIND_DATAA fd;
|
||||
@@ -662,7 +678,7 @@ stk_module_event_t *platform_directory_watch_check(
|
||||
int fd = (int)(long)handle;
|
||||
char buf[STK_EVENT_BUFFER];
|
||||
ssize_t len;
|
||||
size_t index = 0, count = 0, i, write_idx;
|
||||
size_t index = 0, count = 0, i, write_index;
|
||||
stk_module_event_t *evs;
|
||||
char *ptr, *end;
|
||||
struct inotify_event *e;
|
||||
@@ -760,20 +776,18 @@ stk_module_event_t *platform_directory_watch_check(
|
||||
}
|
||||
}
|
||||
|
||||
write_idx = 0;
|
||||
write_index = 0;
|
||||
for (i = 0; i < index; ++i) {
|
||||
if (evs[i] != -1) {
|
||||
if (write_idx != i) {
|
||||
evs[write_idx] = evs[i];
|
||||
strncpy((*file_list)[write_idx],
|
||||
(*file_list)[i], STK_PATH_MAX - 1);
|
||||
(*file_list)[write_idx][STK_PATH_MAX - 1] =
|
||||
'\0';
|
||||
if (write_index != i) {
|
||||
evs[write_index] = evs[i];
|
||||
memmove((*file_list)[write_index],
|
||||
(*file_list)[i], STK_PATH_MAX);
|
||||
}
|
||||
write_idx++;
|
||||
write_index++;
|
||||
}
|
||||
}
|
||||
index = write_idx;
|
||||
index = write_index;
|
||||
|
||||
*out_count = index;
|
||||
return evs;
|
||||
@@ -1012,3 +1026,25 @@ no_change:
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void platform_get_timestamp(char *buffer, size_t size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
SYSTEMTIME st;
|
||||
GetLocalTime(&st);
|
||||
sprintf(buffer, "%04d-%02d-%02d %02d:%02d:%02d.%03d", st.wYear,
|
||||
st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond,
|
||||
st.wMilliseconds);
|
||||
#else
|
||||
struct timeval tv;
|
||||
struct tm *tm_info;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
tm_info = localtime(&tv.tv_sec);
|
||||
|
||||
sprintf(buffer, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
|
||||
tm_info->tm_year + 1900, tm_info->tm_mon + 1, tm_info->tm_mday,
|
||||
tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec,
|
||||
(int)(tv.tv_usec / 1000));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "stk.h"
|
||||
#include "platform.h"
|
||||
#include "stk_log.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -16,11 +15,11 @@ extern char (*stk_module_ids)[STK_MOD_ID_BUFFER];
|
||||
|
||||
extern size_t module_count;
|
||||
|
||||
uint8_t stk_initialized = 0;
|
||||
unsigned char stk_flags = STK_FLAG_LOGGING_ENABLED;
|
||||
|
||||
static char stk_mod_dir[STK_PATH_MAX_OS] = "mods";
|
||||
static char stk_tmp_name[STK_MOD_ID_BUFFER] = ".tmp";
|
||||
static char stk_tmp_dir[STK_PATH_MAX_OS] = "mods/.tmp";
|
||||
static char stk_tmp_dir[STK_PATH_MAX_OS] = "";
|
||||
static void *watch_handle = NULL;
|
||||
|
||||
char (*platform_directory_init_scan(const char *path,
|
||||
@@ -30,18 +29,18 @@ void platform_directory_watch_stop(void *handle);
|
||||
stk_module_event_t *platform_directory_watch_check(
|
||||
void *handle, char (**file_list)[STK_PATH_MAX], size_t *out_count,
|
||||
char (*loaded_module_ids)[STK_MOD_ID_BUFFER], const size_t loaded_count);
|
||||
uint8_t platform_mkdir(const char *path);
|
||||
uint8_t platform_copy_file(const char *from, const char *to);
|
||||
uint8_t platform_remove_dir(const char *path);
|
||||
unsigned char platform_mkdir(const char *path);
|
||||
unsigned char platform_copy_file(const char *from, const char *to);
|
||||
unsigned char platform_remove_dir(const char *path);
|
||||
|
||||
void extract_module_id(const char *path, char *out_id);
|
||||
int is_mod_loaded(const char *module_id);
|
||||
|
||||
size_t stk_module_count(void);
|
||||
uint8_t stk_module_load(const char *path, int index);
|
||||
uint8_t stk_module_load_init(const char *path, int index);
|
||||
uint8_t stk_module_init_memory(size_t capacity);
|
||||
uint8_t stk_module_realloc_memory(size_t new_capacity);
|
||||
unsigned char stk_module_load(const char *path, int index);
|
||||
unsigned char stk_module_load_init(const char *path, int index);
|
||||
unsigned char stk_module_init_memory(size_t capacity);
|
||||
unsigned char stk_module_realloc_memory(size_t new_capacity);
|
||||
void stk_module_unload(size_t index);
|
||||
void stk_module_unload_all(void);
|
||||
|
||||
@@ -70,7 +69,7 @@ static const char *stk_error_string(int error_code)
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t stk_init(void)
|
||||
unsigned char stk_init(void)
|
||||
{
|
||||
char (*files)[STK_PATH_MAX] = NULL;
|
||||
size_t file_count, i, successful_loads = 0;
|
||||
@@ -78,6 +77,8 @@ uint8_t stk_init(void)
|
||||
char tmp_path[STK_PATH_MAX_OS];
|
||||
int load_result;
|
||||
|
||||
platform_mkdir(stk_mod_dir);
|
||||
build_path(stk_tmp_dir, sizeof(stk_tmp_dir), stk_mod_dir, stk_tmp_name);
|
||||
if (platform_mkdir(stk_tmp_dir) != STK_PLATFORM_OPERATION_SUCCESS) {
|
||||
char (*test_scan)[STK_PATH_MAX];
|
||||
size_t test_count;
|
||||
@@ -87,7 +88,7 @@ uint8_t stk_init(void)
|
||||
if (test_scan)
|
||||
free(test_scan);
|
||||
if (!test_scan && test_count == 0) {
|
||||
stk_log(stderr,
|
||||
stk_log(STK_LOG_ERROR,
|
||||
"FATAL: Cannot create temp directory: %s",
|
||||
stk_tmp_dir);
|
||||
return STK_INIT_TMPDIR_ERROR;
|
||||
@@ -97,7 +98,7 @@ uint8_t stk_init(void)
|
||||
files = platform_directory_init_scan(stk_mod_dir, &file_count);
|
||||
|
||||
if (file_count > 0 && stk_module_init_memory(file_count) != 0) {
|
||||
stk_log(stderr, "FATAL: Memory allocation failed");
|
||||
stk_log(STK_LOG_ERROR, "FATAL: Memory allocation failed");
|
||||
return STK_INIT_MEMORY_ERROR;
|
||||
}
|
||||
|
||||
@@ -110,7 +111,8 @@ uint8_t stk_init(void)
|
||||
|
||||
if (platform_copy_file(full_path, tmp_path) !=
|
||||
STK_PLATFORM_OPERATION_SUCCESS) {
|
||||
stk_log(stderr, "Failed to copy %s to temp directory",
|
||||
stk_log(STK_LOG_ERROR,
|
||||
"Failed to copy %s to temp directory",
|
||||
files[i]);
|
||||
continue;
|
||||
}
|
||||
@@ -118,7 +120,7 @@ uint8_t stk_init(void)
|
||||
load_result = stk_module_load_init(tmp_path, successful_loads);
|
||||
|
||||
if (load_result != STK_MOD_INIT_SUCCESS) {
|
||||
stk_log(stderr, "Failed to load module %s: %s",
|
||||
stk_log(STK_LOG_ERROR, "Failed to load module %s: %s",
|
||||
files[i], stk_error_string(load_result));
|
||||
} else {
|
||||
successful_loads++;
|
||||
@@ -134,17 +136,18 @@ uint8_t stk_init(void)
|
||||
scanned:
|
||||
watch_handle = platform_directory_watch_start(stk_mod_dir);
|
||||
if (!watch_handle) {
|
||||
stk_log(stderr, "FATAL: Cannot start directory watch on %s",
|
||||
stk_log(STK_LOG_ERROR,
|
||||
"FATAL: Cannot start directory watch on %s",
|
||||
stk_mod_dir);
|
||||
stk_module_unload_all();
|
||||
return STK_INIT_WATCH_ERROR;
|
||||
}
|
||||
|
||||
stk_log(stdout, "stk v%s initialized! Loaded %lu mod%s from %s/",
|
||||
stk_log(STK_LOG_INFO, "stk v%s initialized! Loaded %lu mod%s from %s/",
|
||||
STK_VERSION_STRING, module_count, module_count != 1 ? "s" : "",
|
||||
stk_mod_dir);
|
||||
|
||||
stk_initialized = 1;
|
||||
stk_flags |= STK_FLAG_INITIALIZED;
|
||||
return STK_INIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -159,12 +162,13 @@ void stk_shutdown(void)
|
||||
|
||||
if (platform_remove_dir(stk_tmp_dir) !=
|
||||
STK_PLATFORM_OPERATION_SUCCESS) {
|
||||
stk_log(stderr, "Warning: failed to remove temp directory %s",
|
||||
stk_log(STK_LOG_WARN,
|
||||
"Warning: failed to remove temp directory %s",
|
||||
stk_tmp_dir);
|
||||
}
|
||||
|
||||
stk_initialized = 0;
|
||||
stk_log(stdout, "stk shutdown");
|
||||
stk_flags &= ~STK_FLAG_INITIALIZED;
|
||||
stk_log(STK_LOG_INFO, "stk shutdown");
|
||||
}
|
||||
|
||||
size_t stk_poll(void)
|
||||
@@ -172,8 +176,7 @@ size_t stk_poll(void)
|
||||
char (*file_list)[STK_PATH_MAX] = NULL;
|
||||
stk_module_event_t *events = NULL;
|
||||
size_t i, file_count = 0, reload_count = 0, load_count = 0,
|
||||
unload_count = 0, reload_index = 0, load_index = 0,
|
||||
unload_index = 0;
|
||||
unload_count = 0;
|
||||
int *reloaded_mod_indices = NULL, *reloaded_mod_file_indices = NULL,
|
||||
*unloaded_mod_indices = NULL, *loaded_mod_indices = NULL;
|
||||
size_t remaining_loads, new_capacity, holes_to_fill;
|
||||
@@ -208,20 +211,31 @@ size_t stk_poll(void)
|
||||
unloaded_mod_indices = malloc(unload_count * sizeof(int));
|
||||
loaded_mod_indices = malloc(load_count * sizeof(int));
|
||||
|
||||
reload_count = 0;
|
||||
unload_count = 0;
|
||||
load_count = 0;
|
||||
|
||||
for (i = 0; i < file_count; ++i) {
|
||||
int mod_index;
|
||||
extract_module_id(file_list[i], mod_id);
|
||||
switch (events[i]) {
|
||||
case STK_MOD_LOAD:
|
||||
loaded_mod_indices[load_index++] = i;
|
||||
loaded_mod_indices[load_count++] = i;
|
||||
break;
|
||||
case STK_MOD_RELOAD:
|
||||
reloaded_mod_file_indices[reload_index] = i;
|
||||
reloaded_mod_indices[reload_index++] =
|
||||
is_mod_loaded(mod_id);
|
||||
mod_index = is_mod_loaded(mod_id);
|
||||
if (mod_index >= 0) {
|
||||
reloaded_mod_file_indices[reload_count] = i;
|
||||
reloaded_mod_indices[reload_count] = mod_index;
|
||||
reload_count++;
|
||||
}
|
||||
break;
|
||||
case STK_MOD_UNLOAD:
|
||||
unloaded_mod_indices[unload_index++] =
|
||||
is_mod_loaded(mod_id);
|
||||
mod_index = is_mod_loaded(mod_id);
|
||||
if (mod_index >= 0) {
|
||||
unloaded_mod_indices[unload_count] = mod_index;
|
||||
unload_count++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -251,18 +265,18 @@ begin_operations:
|
||||
build_path(tmp_path, sizeof(tmp_path), stk_tmp_dir,
|
||||
file_list[file_index]);
|
||||
|
||||
stk_module_unload(mod_index);
|
||||
|
||||
if (platform_copy_file(full_path, tmp_path) !=
|
||||
STK_PLATFORM_OPERATION_SUCCESS) {
|
||||
stk_log(stderr, "Failed to copy %s for reload",
|
||||
stk_log(STK_LOG_ERROR, "Failed to copy %s for reload",
|
||||
file_list[file_index]);
|
||||
continue;
|
||||
}
|
||||
|
||||
stk_module_unload(mod_index);
|
||||
|
||||
load_result = stk_module_load(tmp_path, mod_index);
|
||||
if (load_result != STK_MOD_INIT_SUCCESS) {
|
||||
stk_log(stderr, "Failed to reload module %s: %s",
|
||||
stk_log(STK_LOG_ERROR, "Failed to reload module %s: %s",
|
||||
file_list[file_index],
|
||||
stk_error_string(load_result));
|
||||
}
|
||||
@@ -280,14 +294,14 @@ begin_operations:
|
||||
|
||||
if (platform_copy_file(full_path, tmp_path) !=
|
||||
STK_PLATFORM_OPERATION_SUCCESS) {
|
||||
stk_log(stderr, "Failed to copy %s for loading",
|
||||
stk_log(STK_LOG_ERROR, "Failed to copy %s for loading",
|
||||
file_list[file_index]);
|
||||
continue;
|
||||
}
|
||||
|
||||
load_result = stk_module_load(tmp_path, target_index);
|
||||
if (load_result != STK_MOD_INIT_SUCCESS) {
|
||||
stk_log(stderr, "Failed to load module %s: %s",
|
||||
stk_log(STK_LOG_ERROR, "Failed to load module %s: %s",
|
||||
file_list[file_index],
|
||||
stk_error_string(load_result));
|
||||
}
|
||||
@@ -312,7 +326,7 @@ append_modules:
|
||||
|
||||
if (platform_copy_file(full_path, tmp_path) !=
|
||||
STK_PLATFORM_OPERATION_SUCCESS) {
|
||||
stk_log(stderr, "Failed to copy %s for loading",
|
||||
stk_log(STK_LOG_ERROR, "Failed to copy %s for loading",
|
||||
file_list[file_index]);
|
||||
continue;
|
||||
}
|
||||
@@ -320,7 +334,7 @@ append_modules:
|
||||
load_result = stk_module_load(tmp_path, module_count +
|
||||
successful_appends);
|
||||
if (load_result != STK_MOD_INIT_SUCCESS) {
|
||||
stk_log(stderr, "Failed to load module %s: %s",
|
||||
stk_log(STK_LOG_ERROR, "Failed to load module %s: %s",
|
||||
file_list[file_index],
|
||||
stk_error_string(load_result));
|
||||
} else {
|
||||
@@ -371,7 +385,7 @@ finish_poll:
|
||||
|
||||
void stk_set_mod_dir(const char *path)
|
||||
{
|
||||
if (!path || stk_initialized)
|
||||
if (!path || (stk_flags & STK_FLAG_INITIALIZED))
|
||||
return;
|
||||
|
||||
strncpy(stk_mod_dir, path, STK_PATH_MAX_OS - 1);
|
||||
@@ -389,7 +403,7 @@ void stk_set_mod_dir(const char *path)
|
||||
|
||||
void stk_set_tmp_dir_name(const char *name)
|
||||
{
|
||||
if (!name || stk_initialized)
|
||||
if (!name || (stk_flags & STK_FLAG_INITIALIZED))
|
||||
return;
|
||||
|
||||
strncpy(stk_tmp_name, name, STK_MOD_ID_BUFFER - 1);
|
||||
@@ -402,3 +416,16 @@ void stk_set_tmp_dir_name(const char *name)
|
||||
strncat(stk_tmp_dir, stk_tmp_name,
|
||||
STK_PATH_MAX_OS - strlen(stk_tmp_dir) - 1);
|
||||
}
|
||||
|
||||
void stk_set_logging_enabled(unsigned char enabled)
|
||||
{
|
||||
if (enabled)
|
||||
stk_flags |= STK_FLAG_LOGGING_ENABLED;
|
||||
else
|
||||
stk_flags &= ~STK_FLAG_LOGGING_ENABLED;
|
||||
}
|
||||
|
||||
unsigned char stk_is_logging_enabled(void)
|
||||
{
|
||||
return (stk_flags & STK_FLAG_LOGGING_ENABLED) != 0;
|
||||
}
|
||||
|
||||
+77
-5
@@ -1,14 +1,86 @@
|
||||
#include "stk_log.h"
|
||||
#include "stk.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
void stk_log(FILE *fp, const char *fmt, ...)
|
||||
#define STK_LOG_TIMESTAMP_BUFFER 32
|
||||
|
||||
extern unsigned char stk_flags;
|
||||
void platform_get_timestamp(char *buffer, size_t size);
|
||||
|
||||
static FILE *log_output = NULL;
|
||||
static char log_prefix[STK_LOG_PREFIX_BUFFER] = "stk";
|
||||
static stk_log_level_t min_log_level = STK_LOG_INFO;
|
||||
|
||||
static const char *get_level_string(stk_log_level_t level)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
char *level_str = "";
|
||||
switch (level) {
|
||||
case STK_LOG_ERROR:
|
||||
level_str = "ERROR";
|
||||
break;
|
||||
case STK_LOG_WARN:
|
||||
level_str = "WARN";
|
||||
break;
|
||||
case STK_LOG_INFO:
|
||||
level_str = "INFO";
|
||||
break;
|
||||
case STK_LOG_DEBUG:
|
||||
level_str = "DEBUG";
|
||||
break;
|
||||
}
|
||||
|
||||
vfprintf(fp, fmt, args);
|
||||
fputc('\n', fp);
|
||||
return level_str;
|
||||
}
|
||||
|
||||
void stk_set_log_output(FILE *fp)
|
||||
{
|
||||
if (fp == NULL)
|
||||
stk_flags &= ~STK_FLAG_LOGGING_ENABLED;
|
||||
|
||||
log_output = fp;
|
||||
}
|
||||
|
||||
void stk_set_log_prefix(const char *prefix)
|
||||
{
|
||||
if (!prefix) {
|
||||
log_prefix[0] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
strncpy(log_prefix, prefix, STK_LOG_PREFIX_BUFFER - 1);
|
||||
log_prefix[STK_LOG_PREFIX_BUFFER - 1] = '\0';
|
||||
}
|
||||
|
||||
void stk_set_log_level(stk_log_level_t level) { min_log_level = level; }
|
||||
|
||||
void stk_log(stk_log_level_t level, const char *fmt, ...)
|
||||
{
|
||||
FILE *output;
|
||||
const char *level_str;
|
||||
char timestamp[STK_LOG_TIMESTAMP_BUFFER];
|
||||
va_list args;
|
||||
|
||||
if (!(stk_flags & STK_FLAG_LOGGING_ENABLED))
|
||||
return;
|
||||
|
||||
if (level < min_log_level)
|
||||
return;
|
||||
|
||||
output = log_output ? log_output : stdout;
|
||||
level_str = get_level_string(level);
|
||||
platform_get_timestamp(timestamp, sizeof(timestamp));
|
||||
|
||||
if (log_prefix[0] != '\0')
|
||||
fprintf(output, "%s [%s] [%s] ", timestamp, log_prefix,
|
||||
level_str);
|
||||
else
|
||||
fprintf(output, "%s [%s] ", timestamp, level_str);
|
||||
|
||||
va_start(args, fmt);
|
||||
vfprintf(output, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
fputc('\n', output);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ CFLAGS = -Wall -Wpedantic -I../include -std=c89
|
||||
LDFLAGS = -L../bin/debug -lstk
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
SHELL := cmd.exe
|
||||
.SHELLFLAGS := /c
|
||||
MODULE_EXT = .dll
|
||||
EXE_EXT = .exe
|
||||
else
|
||||
|
||||
+5
-4
@@ -31,8 +31,8 @@ void inthand(int signum)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
uint8_t init_result;
|
||||
uint64_t iterations = 0;
|
||||
unsigned char init_result;
|
||||
size_t iterations = 0;
|
||||
|
||||
printf("stk test - CTRL+C to exit\n");
|
||||
|
||||
@@ -55,12 +55,13 @@ int main(int argc, char **argv)
|
||||
while (!stop) {
|
||||
size_t events = stk_poll();
|
||||
if (events > 0)
|
||||
printf("Poll: %lu module event(s) detected\n", (unsigned long) events);
|
||||
printf("Poll: %lu module event(s) detected\n",
|
||||
(unsigned long)events);
|
||||
|
||||
iterations++;
|
||||
if (iterations % 5 == 0) {
|
||||
printf("Still running... (iteration %lu)\n",
|
||||
(unsigned long) iterations);
|
||||
(unsigned long)iterations);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
Sleep(1000);
|
||||
|
||||
Reference in New Issue
Block a user