Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 345cd35f19 | |||
| c2b9571c2d | |||
| 3f7f216c92 | |||
| 70d50dda92 | |||
| 70e9ec2fc3 | |||
| 110b7ffca8 | |||
| 26fb19a7f5 | |||
| bcb1795218 | |||
| fb0d8adb8f | |||
| 2c4d27f915 | |||
| 96fb957991 | |||
| 0cbee45ad2 |
+74
-1
@@ -7,6 +7,73 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [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
|
## [0.0.2] - 2026-02-09
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
@@ -37,6 +104,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Dependency management and versioning not yet implemented
|
- Dependency management and versioning not yet implemented
|
||||||
- API is unstable and subject to change in future releases
|
- 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.2]: https://github.com/anth64/stk/releases/tag/v0.0.2
|
||||||
[0.0.1]: https://github.com/anth64/stk/releases/tag/v0.0.1
|
[0.0.1]: https://github.com/anth64/stk/releases/tag/v0.0.1
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ stk_init();
|
|||||||
### API Reference
|
### API Reference
|
||||||
|
|
||||||
#### Initialization
|
#### 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
|
- `void stk_shutdown(void)` - Shutdown and cleanup all modules
|
||||||
|
|
||||||
#### Runtime
|
#### Runtime
|
||||||
@@ -169,22 +169,31 @@ stk_init();
|
|||||||
- `void stk_set_module_init_fn(const char *name)` - Set module init function name
|
- `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
|
- `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
|
## 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
|
### What Works
|
||||||
- Cross-platform module loading and hot-reloading
|
- Cross-platform module loading and hot-reloading
|
||||||
- File watching (inotify/kqueue/FindFirstFile)
|
- File watching (inotify/kqueue/FindFirstFile)
|
||||||
- Basic error handling
|
- Robust hot-reload even during extremely rapid file changes
|
||||||
- Stable hot-reload even during rapid file changes (Linux fix in 0.0.2)
|
- Enhanced logging with levels, timestamps, and filtering
|
||||||
|
- Runtime-configurable logging behavior
|
||||||
|
|
||||||
### In Progress (Phase 1)
|
### In Progress (Phase 1)
|
||||||
- Complete logging system (log levels, verbosity, output configuration)
|
|
||||||
- Module metadata (name, version, description)
|
- Module metadata (name, version, description)
|
||||||
- Dependency management and versioning
|
- Dependency management and versioning
|
||||||
|
|
||||||
|
|||||||
+8
-2
@@ -2,10 +2,10 @@
|
|||||||
#define STK_H
|
#define STK_H
|
||||||
|
|
||||||
#include "stk_version.h"
|
#include "stk_version.h"
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
/* Buffers */
|
/* Buffers */
|
||||||
|
#define STK_LOG_PREFIX_BUFFER 64
|
||||||
#define STK_MOD_DIR_BUFFER 256
|
#define STK_MOD_DIR_BUFFER 256
|
||||||
#define STK_MOD_ID_BUFFER 64
|
#define STK_MOD_ID_BUFFER 64
|
||||||
#define STK_PATH_MAX 256
|
#define STK_PATH_MAX 256
|
||||||
@@ -31,6 +31,10 @@
|
|||||||
#define STK_PLATFORM_REMOVE_DIR_ERROR 3
|
#define STK_PLATFORM_REMOVE_DIR_ERROR 3
|
||||||
#define STK_PLATFORM_REMOVE_FILE_ERROR 4
|
#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)
|
#if defined(__linux__) || defined(_WIN32)
|
||||||
#define STK_EVENT_BUFFER 4096
|
#define STK_EVENT_BUFFER 4096
|
||||||
#endif
|
#endif
|
||||||
@@ -55,7 +59,7 @@ typedef enum {
|
|||||||
STK_MOD_RELOAD
|
STK_MOD_RELOAD
|
||||||
} stk_module_event_t;
|
} stk_module_event_t;
|
||||||
|
|
||||||
uint8_t stk_init(void);
|
unsigned char stk_init(void);
|
||||||
void stk_shutdown(void);
|
void stk_shutdown(void);
|
||||||
size_t stk_module_count(void);
|
size_t stk_module_count(void);
|
||||||
size_t stk_poll(void);
|
size_t stk_poll(void);
|
||||||
@@ -63,6 +67,8 @@ void stk_set_mod_dir(const char *path);
|
|||||||
void stk_set_tmp_dir_name(const char *name);
|
void stk_set_tmp_dir_name(const char *name);
|
||||||
void stk_set_module_init_fn(const char *name);
|
void stk_set_module_init_fn(const char *name);
|
||||||
void stk_set_module_shutdown_fn(const char *name);
|
void stk_set_module_shutdown_fn(const char *name);
|
||||||
|
void stk_set_logging_enabled(unsigned char enabled);
|
||||||
|
unsigned char stk_is_logging_enabled(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-1
@@ -7,7 +7,18 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#define STK_VERSION_H
|
#define STK_VERSION_H
|
||||||
|
|
||||||
#define STK_VERSION_MAJOR 0
|
#define STK_VERSION_MAJOR 0
|
||||||
#define STK_VERSION_MINOR 0
|
#define STK_VERSION_MINOR 1
|
||||||
#define STK_VERSION_PATCH 2
|
#define STK_VERSION_PATCH 2
|
||||||
|
|
||||||
#define STK_STRINGIFY_HELPER(x) #x
|
#define STK_STRINGIFY_HELPER(x) #x
|
||||||
|
|||||||
+8
-9
@@ -1,6 +1,5 @@
|
|||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "stk.h"
|
#include "stk.h"
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -18,7 +17,7 @@ void **stk_handles = NULL;
|
|||||||
stk_init_mod_func *stk_inits = NULL;
|
stk_init_mod_func *stk_inits = NULL;
|
||||||
stk_shutdown_mod_func *stk_shutdowns = NULL;
|
stk_shutdown_mod_func *stk_shutdowns = NULL;
|
||||||
|
|
||||||
extern uint8_t stk_initialized;
|
extern unsigned char stk_flags;
|
||||||
|
|
||||||
static char stk_mod_init_name[STK_MOD_FUNC_NAME_BUFFER] = "stk_mod_init";
|
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] =
|
static char stk_mod_shutdown_name[STK_MOD_FUNC_NAME_BUFFER] =
|
||||||
@@ -43,7 +42,7 @@ void extract_module_id(const char *path, char *out_id)
|
|||||||
*dot = '\0';
|
*dot = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t is_valid_module_file(const char *filename)
|
unsigned char is_valid_module_file(const char *filename)
|
||||||
{
|
{
|
||||||
const char *ext;
|
const char *ext;
|
||||||
size_t name_len;
|
size_t name_len;
|
||||||
@@ -72,7 +71,7 @@ int is_mod_loaded(const char *module_name)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t stk_module_load(const char *path, int index)
|
unsigned char stk_module_load(const char *path, int index)
|
||||||
{
|
{
|
||||||
void *handle;
|
void *handle;
|
||||||
stk_init_mod_func init_func;
|
stk_init_mod_func init_func;
|
||||||
@@ -121,7 +120,7 @@ uint8_t stk_module_load(const char *path, int index)
|
|||||||
return STK_MOD_INIT_SUCCESS;
|
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;
|
int result;
|
||||||
result = stk_module_load(path, index);
|
result = stk_module_load(path, index);
|
||||||
@@ -155,7 +154,7 @@ void stk_module_free_memory(void)
|
|||||||
stk_shutdowns = NULL;
|
stk_shutdowns = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
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_module_ids = malloc(capacity * sizeof(*stk_module_ids));
|
||||||
stk_handles = malloc(capacity * sizeof(void *));
|
stk_handles = malloc(capacity * sizeof(void *));
|
||||||
@@ -170,7 +169,7 @@ uint8_t stk_module_init_memory(size_t capacity)
|
|||||||
return STK_INIT_SUCCESS;
|
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;
|
char (*new_module_ids)[STK_MOD_ID_BUFFER] = NULL;
|
||||||
void **new_handles = NULL;
|
void **new_handles = NULL;
|
||||||
@@ -254,7 +253,7 @@ void stk_module_unload_all(void)
|
|||||||
|
|
||||||
void stk_set_module_init_fn(const char *name)
|
void stk_set_module_init_fn(const char *name)
|
||||||
{
|
{
|
||||||
if (!name || stk_initialized)
|
if (!name || (stk_flags & STK_FLAG_INITIALIZED))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
strncpy(stk_mod_init_name, name, STK_MOD_FUNC_NAME_BUFFER - 1);
|
strncpy(stk_mod_init_name, name, STK_MOD_FUNC_NAME_BUFFER - 1);
|
||||||
@@ -263,7 +262,7 @@ void stk_set_module_init_fn(const char *name)
|
|||||||
|
|
||||||
void stk_set_module_shutdown_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;
|
return;
|
||||||
|
|
||||||
strncpy(stk_mod_shutdown_name, name, STK_MOD_FUNC_NAME_BUFFER - 1);
|
strncpy(stk_mod_shutdown_name, name, STK_MOD_FUNC_NAME_BUFFER - 1);
|
||||||
|
|||||||
+63
-27
@@ -1,38 +1,34 @@
|
|||||||
#include "stk.h"
|
#include "stk.h"
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
#include <dirent.h>
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#include <sys/inotify.h>
|
#include <sys/inotify.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#else
|
#else
|
||||||
#include <dirent.h>
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/event.h>
|
#include <sys/event.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int is_mod_loaded(const char *module_name);
|
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);
|
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];
|
char full_path[STK_PATH_MAX_OS];
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -108,12 +104,32 @@ typedef struct {
|
|||||||
} platform_watch_context_t;
|
} platform_watch_context_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t platform_mkdir(const char *path)
|
unsigned char platform_mkdir(const char *path)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return CreateDirectoryA(path, NULL) ? STK_PLATFORM_OPERATION_SUCCESS
|
DWORD attrib;
|
||||||
: STK_PLATFORM_MKDIR_ERROR;
|
|
||||||
|
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
|
#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
|
return mkdir(path, 0755) == 0 ? STK_PLATFORM_OPERATION_SUCCESS
|
||||||
: STK_PLATFORM_MKDIR_ERROR;
|
: STK_PLATFORM_MKDIR_ERROR;
|
||||||
#endif
|
#endif
|
||||||
@@ -130,7 +146,7 @@ int platform_remove_file(const char *path)
|
|||||||
#endif
|
#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];
|
char buf[STK_PATH_MAX_OS];
|
||||||
int ret = STK_PLATFORM_FILE_COPY_ERROR;
|
int ret = STK_PLATFORM_FILE_COPY_ERROR;
|
||||||
@@ -203,7 +219,7 @@ done:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t platform_remove_dir(const char *path)
|
unsigned char platform_remove_dir(const char *path)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
WIN32_FIND_DATAA fd;
|
WIN32_FIND_DATAA fd;
|
||||||
@@ -662,7 +678,7 @@ stk_module_event_t *platform_directory_watch_check(
|
|||||||
int fd = (int)(long)handle;
|
int fd = (int)(long)handle;
|
||||||
char buf[STK_EVENT_BUFFER];
|
char buf[STK_EVENT_BUFFER];
|
||||||
ssize_t len;
|
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;
|
stk_module_event_t *evs;
|
||||||
char *ptr, *end;
|
char *ptr, *end;
|
||||||
struct inotify_event *e;
|
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) {
|
for (i = 0; i < index; ++i) {
|
||||||
if (evs[i] != -1) {
|
if (evs[i] != -1) {
|
||||||
if (write_idx != i) {
|
if (write_index != i) {
|
||||||
evs[write_idx] = evs[i];
|
evs[write_index] = evs[i];
|
||||||
strncpy((*file_list)[write_idx],
|
memmove((*file_list)[write_index],
|
||||||
(*file_list)[i], STK_PATH_MAX - 1);
|
(*file_list)[i], STK_PATH_MAX);
|
||||||
(*file_list)[write_idx][STK_PATH_MAX - 1] =
|
|
||||||
'\0';
|
|
||||||
}
|
}
|
||||||
write_idx++;
|
write_index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
index = write_idx;
|
index = write_index;
|
||||||
|
|
||||||
*out_count = index;
|
*out_count = index;
|
||||||
return evs;
|
return evs;
|
||||||
@@ -1012,3 +1026,25 @@ no_change:
|
|||||||
return NULL;
|
return NULL;
|
||||||
#endif
|
#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 "stk.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "stk_log.h"
|
#include "stk_log.h"
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -16,11 +15,11 @@ extern char (*stk_module_ids)[STK_MOD_ID_BUFFER];
|
|||||||
|
|
||||||
extern size_t module_count;
|
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_mod_dir[STK_PATH_MAX_OS] = "mods";
|
||||||
static char stk_tmp_name[STK_MOD_ID_BUFFER] = ".tmp";
|
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;
|
static void *watch_handle = NULL;
|
||||||
|
|
||||||
char (*platform_directory_init_scan(const char *path,
|
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(
|
stk_module_event_t *platform_directory_watch_check(
|
||||||
void *handle, char (**file_list)[STK_PATH_MAX], size_t *out_count,
|
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);
|
char (*loaded_module_ids)[STK_MOD_ID_BUFFER], const size_t loaded_count);
|
||||||
uint8_t platform_mkdir(const char *path);
|
unsigned char platform_mkdir(const char *path);
|
||||||
uint8_t platform_copy_file(const char *from, const char *to);
|
unsigned char platform_copy_file(const char *from, const char *to);
|
||||||
uint8_t platform_remove_dir(const char *path);
|
unsigned char platform_remove_dir(const char *path);
|
||||||
|
|
||||||
void extract_module_id(const char *path, char *out_id);
|
void extract_module_id(const char *path, char *out_id);
|
||||||
int is_mod_loaded(const char *module_id);
|
int is_mod_loaded(const char *module_id);
|
||||||
|
|
||||||
size_t stk_module_count(void);
|
size_t stk_module_count(void);
|
||||||
uint8_t stk_module_load(const char *path, int index);
|
unsigned char stk_module_load(const char *path, int index);
|
||||||
uint8_t stk_module_load_init(const char *path, int index);
|
unsigned char stk_module_load_init(const char *path, int index);
|
||||||
uint8_t stk_module_init_memory(size_t capacity);
|
unsigned char stk_module_init_memory(size_t capacity);
|
||||||
uint8_t stk_module_realloc_memory(size_t new_capacity);
|
unsigned char stk_module_realloc_memory(size_t new_capacity);
|
||||||
void stk_module_unload(size_t index);
|
void stk_module_unload(size_t index);
|
||||||
void stk_module_unload_all(void);
|
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;
|
char (*files)[STK_PATH_MAX] = NULL;
|
||||||
size_t file_count, i, successful_loads = 0;
|
size_t file_count, i, successful_loads = 0;
|
||||||
@@ -78,6 +77,8 @@ uint8_t stk_init(void)
|
|||||||
char tmp_path[STK_PATH_MAX_OS];
|
char tmp_path[STK_PATH_MAX_OS];
|
||||||
int load_result;
|
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) {
|
if (platform_mkdir(stk_tmp_dir) != STK_PLATFORM_OPERATION_SUCCESS) {
|
||||||
char (*test_scan)[STK_PATH_MAX];
|
char (*test_scan)[STK_PATH_MAX];
|
||||||
size_t test_count;
|
size_t test_count;
|
||||||
@@ -87,7 +88,7 @@ uint8_t stk_init(void)
|
|||||||
if (test_scan)
|
if (test_scan)
|
||||||
free(test_scan);
|
free(test_scan);
|
||||||
if (!test_scan && test_count == 0) {
|
if (!test_scan && test_count == 0) {
|
||||||
stk_log(stderr,
|
stk_log(STK_LOG_ERROR,
|
||||||
"FATAL: Cannot create temp directory: %s",
|
"FATAL: Cannot create temp directory: %s",
|
||||||
stk_tmp_dir);
|
stk_tmp_dir);
|
||||||
return STK_INIT_TMPDIR_ERROR;
|
return STK_INIT_TMPDIR_ERROR;
|
||||||
@@ -97,7 +98,7 @@ uint8_t stk_init(void)
|
|||||||
files = platform_directory_init_scan(stk_mod_dir, &file_count);
|
files = platform_directory_init_scan(stk_mod_dir, &file_count);
|
||||||
|
|
||||||
if (file_count > 0 && stk_module_init_memory(file_count) != 0) {
|
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;
|
return STK_INIT_MEMORY_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +111,8 @@ uint8_t stk_init(void)
|
|||||||
|
|
||||||
if (platform_copy_file(full_path, tmp_path) !=
|
if (platform_copy_file(full_path, tmp_path) !=
|
||||||
STK_PLATFORM_OPERATION_SUCCESS) {
|
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]);
|
files[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -118,7 +120,7 @@ uint8_t stk_init(void)
|
|||||||
load_result = stk_module_load_init(tmp_path, successful_loads);
|
load_result = stk_module_load_init(tmp_path, successful_loads);
|
||||||
|
|
||||||
if (load_result != STK_MOD_INIT_SUCCESS) {
|
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));
|
files[i], stk_error_string(load_result));
|
||||||
} else {
|
} else {
|
||||||
successful_loads++;
|
successful_loads++;
|
||||||
@@ -134,17 +136,18 @@ uint8_t stk_init(void)
|
|||||||
scanned:
|
scanned:
|
||||||
watch_handle = platform_directory_watch_start(stk_mod_dir);
|
watch_handle = platform_directory_watch_start(stk_mod_dir);
|
||||||
if (!watch_handle) {
|
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_mod_dir);
|
||||||
stk_module_unload_all();
|
stk_module_unload_all();
|
||||||
return STK_INIT_WATCH_ERROR;
|
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_VERSION_STRING, module_count, module_count != 1 ? "s" : "",
|
||||||
stk_mod_dir);
|
stk_mod_dir);
|
||||||
|
|
||||||
stk_initialized = 1;
|
stk_flags |= STK_FLAG_INITIALIZED;
|
||||||
return STK_INIT_SUCCESS;
|
return STK_INIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,12 +162,13 @@ void stk_shutdown(void)
|
|||||||
|
|
||||||
if (platform_remove_dir(stk_tmp_dir) !=
|
if (platform_remove_dir(stk_tmp_dir) !=
|
||||||
STK_PLATFORM_OPERATION_SUCCESS) {
|
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_tmp_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
stk_initialized = 0;
|
stk_flags &= ~STK_FLAG_INITIALIZED;
|
||||||
stk_log(stdout, "stk shutdown");
|
stk_log(STK_LOG_INFO, "stk shutdown");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t stk_poll(void)
|
size_t stk_poll(void)
|
||||||
@@ -172,8 +176,7 @@ size_t stk_poll(void)
|
|||||||
char (*file_list)[STK_PATH_MAX] = NULL;
|
char (*file_list)[STK_PATH_MAX] = NULL;
|
||||||
stk_module_event_t *events = NULL;
|
stk_module_event_t *events = NULL;
|
||||||
size_t i, file_count = 0, reload_count = 0, load_count = 0,
|
size_t i, file_count = 0, reload_count = 0, load_count = 0,
|
||||||
unload_count = 0, reload_index = 0, load_index = 0,
|
unload_count = 0;
|
||||||
unload_index = 0;
|
|
||||||
int *reloaded_mod_indices = NULL, *reloaded_mod_file_indices = NULL,
|
int *reloaded_mod_indices = NULL, *reloaded_mod_file_indices = NULL,
|
||||||
*unloaded_mod_indices = NULL, *loaded_mod_indices = NULL;
|
*unloaded_mod_indices = NULL, *loaded_mod_indices = NULL;
|
||||||
size_t remaining_loads, new_capacity, holes_to_fill;
|
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));
|
unloaded_mod_indices = malloc(unload_count * sizeof(int));
|
||||||
loaded_mod_indices = malloc(load_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) {
|
for (i = 0; i < file_count; ++i) {
|
||||||
|
int mod_index;
|
||||||
extract_module_id(file_list[i], mod_id);
|
extract_module_id(file_list[i], mod_id);
|
||||||
switch (events[i]) {
|
switch (events[i]) {
|
||||||
case STK_MOD_LOAD:
|
case STK_MOD_LOAD:
|
||||||
loaded_mod_indices[load_index++] = i;
|
loaded_mod_indices[load_count++] = i;
|
||||||
break;
|
break;
|
||||||
case STK_MOD_RELOAD:
|
case STK_MOD_RELOAD:
|
||||||
reloaded_mod_file_indices[reload_index] = i;
|
mod_index = is_mod_loaded(mod_id);
|
||||||
reloaded_mod_indices[reload_index++] =
|
if (mod_index >= 0) {
|
||||||
is_mod_loaded(mod_id);
|
reloaded_mod_file_indices[reload_count] = i;
|
||||||
|
reloaded_mod_indices[reload_count] = mod_index;
|
||||||
|
reload_count++;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case STK_MOD_UNLOAD:
|
case STK_MOD_UNLOAD:
|
||||||
unloaded_mod_indices[unload_index++] =
|
mod_index = is_mod_loaded(mod_id);
|
||||||
is_mod_loaded(mod_id);
|
if (mod_index >= 0) {
|
||||||
|
unloaded_mod_indices[unload_count] = mod_index;
|
||||||
|
unload_count++;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -251,18 +265,18 @@ begin_operations:
|
|||||||
build_path(tmp_path, sizeof(tmp_path), stk_tmp_dir,
|
build_path(tmp_path, sizeof(tmp_path), stk_tmp_dir,
|
||||||
file_list[file_index]);
|
file_list[file_index]);
|
||||||
|
|
||||||
|
stk_module_unload(mod_index);
|
||||||
|
|
||||||
if (platform_copy_file(full_path, tmp_path) !=
|
if (platform_copy_file(full_path, tmp_path) !=
|
||||||
STK_PLATFORM_OPERATION_SUCCESS) {
|
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]);
|
file_list[file_index]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
stk_module_unload(mod_index);
|
|
||||||
|
|
||||||
load_result = stk_module_load(tmp_path, mod_index);
|
load_result = stk_module_load(tmp_path, mod_index);
|
||||||
if (load_result != STK_MOD_INIT_SUCCESS) {
|
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],
|
file_list[file_index],
|
||||||
stk_error_string(load_result));
|
stk_error_string(load_result));
|
||||||
}
|
}
|
||||||
@@ -280,14 +294,14 @@ begin_operations:
|
|||||||
|
|
||||||
if (platform_copy_file(full_path, tmp_path) !=
|
if (platform_copy_file(full_path, tmp_path) !=
|
||||||
STK_PLATFORM_OPERATION_SUCCESS) {
|
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]);
|
file_list[file_index]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
load_result = stk_module_load(tmp_path, target_index);
|
load_result = stk_module_load(tmp_path, target_index);
|
||||||
if (load_result != STK_MOD_INIT_SUCCESS) {
|
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],
|
file_list[file_index],
|
||||||
stk_error_string(load_result));
|
stk_error_string(load_result));
|
||||||
}
|
}
|
||||||
@@ -312,7 +326,7 @@ append_modules:
|
|||||||
|
|
||||||
if (platform_copy_file(full_path, tmp_path) !=
|
if (platform_copy_file(full_path, tmp_path) !=
|
||||||
STK_PLATFORM_OPERATION_SUCCESS) {
|
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]);
|
file_list[file_index]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -320,7 +334,7 @@ append_modules:
|
|||||||
load_result = stk_module_load(tmp_path, module_count +
|
load_result = stk_module_load(tmp_path, module_count +
|
||||||
successful_appends);
|
successful_appends);
|
||||||
if (load_result != STK_MOD_INIT_SUCCESS) {
|
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],
|
file_list[file_index],
|
||||||
stk_error_string(load_result));
|
stk_error_string(load_result));
|
||||||
} else {
|
} else {
|
||||||
@@ -371,7 +385,7 @@ finish_poll:
|
|||||||
|
|
||||||
void stk_set_mod_dir(const char *path)
|
void stk_set_mod_dir(const char *path)
|
||||||
{
|
{
|
||||||
if (!path || stk_initialized)
|
if (!path || (stk_flags & STK_FLAG_INITIALIZED))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
strncpy(stk_mod_dir, path, STK_PATH_MAX_OS - 1);
|
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)
|
void stk_set_tmp_dir_name(const char *name)
|
||||||
{
|
{
|
||||||
if (!name || stk_initialized)
|
if (!name || (stk_flags & STK_FLAG_INITIALIZED))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
strncpy(stk_tmp_name, name, STK_MOD_ID_BUFFER - 1);
|
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,
|
strncat(stk_tmp_dir, stk_tmp_name,
|
||||||
STK_PATH_MAX_OS - strlen(stk_tmp_dir) - 1);
|
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_log.h"
|
||||||
|
#include "stk.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.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;
|
char *level_str = "";
|
||||||
va_start(args, fmt);
|
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);
|
return level_str;
|
||||||
fputc('\n', fp);
|
}
|
||||||
|
|
||||||
|
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);
|
va_end(args);
|
||||||
|
|
||||||
|
fputc('\n', output);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ CFLAGS = -Wall -Wpedantic -I../include -std=c89
|
|||||||
LDFLAGS = -L../bin/debug -lstk
|
LDFLAGS = -L../bin/debug -lstk
|
||||||
|
|
||||||
ifeq ($(OS),Windows_NT)
|
ifeq ($(OS),Windows_NT)
|
||||||
|
SHELL := cmd.exe
|
||||||
|
.SHELLFLAGS := /c
|
||||||
MODULE_EXT = .dll
|
MODULE_EXT = .dll
|
||||||
EXE_EXT = .exe
|
EXE_EXT = .exe
|
||||||
else
|
else
|
||||||
|
|||||||
+5
-4
@@ -31,8 +31,8 @@ void inthand(int signum)
|
|||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
uint8_t init_result;
|
unsigned char init_result;
|
||||||
uint64_t iterations = 0;
|
size_t iterations = 0;
|
||||||
|
|
||||||
printf("stk test - CTRL+C to exit\n");
|
printf("stk test - CTRL+C to exit\n");
|
||||||
|
|
||||||
@@ -55,12 +55,13 @@ int main(int argc, char **argv)
|
|||||||
while (!stop) {
|
while (!stop) {
|
||||||
size_t events = stk_poll();
|
size_t events = stk_poll();
|
||||||
if (events > 0)
|
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++;
|
iterations++;
|
||||||
if (iterations % 5 == 0) {
|
if (iterations % 5 == 0) {
|
||||||
printf("Still running... (iteration %lu)\n",
|
printf("Still running... (iteration %lu)\n",
|
||||||
(unsigned long) iterations);
|
(unsigned long)iterations);
|
||||||
}
|
}
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
Sleep(1000);
|
Sleep(1000);
|
||||||
|
|||||||
Reference in New Issue
Block a user