blind reformat all files
This commit is contained in:
@@ -10,10 +10,10 @@ extern "C" {
|
|||||||
|
|
||||||
// Return codes for reload_module
|
// Return codes for reload_module
|
||||||
typedef enum {
|
typedef enum {
|
||||||
HI_RELOAD_SUCCESS = 0,
|
HI_RELOAD_SUCCESS = 0,
|
||||||
HI_RELOAD_NOT_FOUND,
|
HI_RELOAD_NOT_FOUND,
|
||||||
HI_RELOAD_CLOSE_ERROR,
|
HI_RELOAD_CLOSE_ERROR,
|
||||||
HI_RELOAD_OPEN_ERROR
|
HI_RELOAD_OPEN_ERROR
|
||||||
} ReloadResult;
|
} ReloadResult;
|
||||||
|
|
||||||
/* Initialiez the module. Must be called before anything else */
|
/* Initialiez the module. Must be called before anything else */
|
||||||
|
|||||||
@@ -33,11 +33,11 @@
|
|||||||
#define SC_ARRAY_H
|
#define SC_ARRAY_H
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#define SC_ARRAY_VERSION "2.0.0"
|
#define SC_ARRAY_VERSION "2.0.0"
|
||||||
|
|
||||||
@@ -53,31 +53,31 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define sc_array_def(T, name) \
|
#define sc_array_def(T, name) \
|
||||||
struct sc_array_##name { \
|
struct sc_array_##name { \
|
||||||
bool oom; \
|
bool oom; \
|
||||||
size_t cap; \
|
size_t cap; \
|
||||||
size_t size; \
|
size_t size; \
|
||||||
/* NOLINTNEXTLINE */ \
|
/* NOLINTNEXTLINE */ \
|
||||||
T *elems; \
|
T *elems; \
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Init array
|
* Init array
|
||||||
* @param a array
|
* @param a array
|
||||||
*/
|
*/
|
||||||
#define sc_array_init(a) \
|
#define sc_array_init(a) \
|
||||||
do { \
|
do { \
|
||||||
memset((a), 0, sizeof(*(a))); \
|
memset((a), 0, sizeof(*(a))); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy array
|
* Destroy array
|
||||||
* @param a array
|
* @param a array
|
||||||
*/
|
*/
|
||||||
#define sc_array_term(a) \
|
#define sc_array_term(a) \
|
||||||
do { \
|
do { \
|
||||||
sc_array_free((a)->elems); \
|
sc_array_free((a)->elems); \
|
||||||
sc_array_init(a); \
|
sc_array_init(a); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add elem to array, call sc_array_oom(v) to see if 'add' failed because of out
|
* Add elem to array, call sc_array_oom(v) to see if 'add' failed because of out
|
||||||
@@ -87,39 +87,38 @@
|
|||||||
* @param k elem
|
* @param k elem
|
||||||
*/
|
*/
|
||||||
#define sc_array_add(a, k) \
|
#define sc_array_add(a, k) \
|
||||||
do { \
|
do { \
|
||||||
const size_t _max = SC_ARRAY_MAX / sizeof(*(a)->elems); \
|
const size_t _max = SC_ARRAY_MAX / sizeof(*(a)->elems); \
|
||||||
size_t _cap; \
|
size_t _cap; \
|
||||||
void *_p; \
|
void *_p; \
|
||||||
\
|
\
|
||||||
if ((a)->cap == (a)->size) { \
|
if ((a)->cap == (a)->size) { \
|
||||||
if ((a)->cap > _max / 2) { \
|
if ((a)->cap > _max / 2) { \
|
||||||
(a)->oom = true; \
|
(a)->oom = true; \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
_cap = (a)->cap == 0 ? 8 : (a)->cap * 2; \
|
_cap = (a)->cap == 0 ? 8 : (a)->cap * 2; \
|
||||||
_p = sc_array_realloc((a)->elems, \
|
_p = sc_array_realloc((a)->elems, _cap * sizeof(*((a)->elems))); \
|
||||||
_cap * sizeof(*((a)->elems))); \
|
if (_p == NULL) { \
|
||||||
if (_p == NULL) { \
|
(a)->oom = true; \
|
||||||
(a)->oom = true; \
|
break; \
|
||||||
break; \
|
} \
|
||||||
} \
|
(a)->cap = _cap; \
|
||||||
(a)->cap = _cap; \
|
(a)->elems = _p; \
|
||||||
(a)->elems = _p; \
|
} \
|
||||||
} \
|
(a)->oom = false; \
|
||||||
(a)->oom = false; \
|
(a)->elems[(a)->size++] = k; \
|
||||||
(a)->elems[(a)->size++] = k; \
|
} while (0)
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes items from the array without deallocating underlying memory
|
* Deletes items from the array without deallocating underlying memory
|
||||||
* @param a array
|
* @param a array
|
||||||
*/
|
*/
|
||||||
#define sc_array_clear(a) \
|
#define sc_array_clear(a) \
|
||||||
do { \
|
do { \
|
||||||
(a)->size = 0; \
|
(a)->size = 0; \
|
||||||
(a)->oom = false; \
|
(a)->oom = false; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param a array
|
* @param a array
|
||||||
@@ -147,17 +146,17 @@
|
|||||||
* @param i element index, If 'i' is out of the range, result is undefined.
|
* @param i element index, If 'i' is out of the range, result is undefined.
|
||||||
*/
|
*/
|
||||||
#define sc_array_del(a, i) \
|
#define sc_array_del(a, i) \
|
||||||
do { \
|
do { \
|
||||||
size_t idx = (i); \
|
size_t idx = (i); \
|
||||||
assert(idx < (a)->size); \
|
assert(idx < (a)->size); \
|
||||||
\
|
\
|
||||||
const size_t _cnt = (a)->size - (idx) - 1; \
|
const size_t _cnt = (a)->size - (idx)-1; \
|
||||||
if (_cnt > 0) { \
|
if (_cnt > 0) { \
|
||||||
memmove(&((a)->elems[idx]), &((a)->elems[idx + 1]), \
|
memmove(&((a)->elems[idx]), &((a)->elems[idx + 1]), \
|
||||||
_cnt * sizeof(*((a)->elems))); \
|
_cnt * sizeof(*((a)->elems))); \
|
||||||
} \
|
} \
|
||||||
(a)->size--; \
|
(a)->size--; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes the element at index i, replaces last element with the deleted
|
* Deletes the element at index i, replaces last element with the deleted
|
||||||
@@ -170,21 +169,21 @@
|
|||||||
* @param i index. If 'i' is out of the range, result is undefined.
|
* @param i index. If 'i' is out of the range, result is undefined.
|
||||||
*/
|
*/
|
||||||
#define sc_array_del_unordered(a, i) \
|
#define sc_array_del_unordered(a, i) \
|
||||||
do { \
|
do { \
|
||||||
size_t idx = (i); \
|
size_t idx = (i); \
|
||||||
assert(idx < (a)->size); \
|
assert(idx < (a)->size); \
|
||||||
(a)->elems[idx] = (a)->elems[(--(a)->size)]; \
|
(a)->elems[idx] = (a)->elems[(--(a)->size)]; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes the last element. If current size is zero, result is undefined.
|
* Deletes the last element. If current size is zero, result is undefined.
|
||||||
* @param a array
|
* @param a array
|
||||||
*/
|
*/
|
||||||
#define sc_array_del_last(a) \
|
#define sc_array_del_last(a) \
|
||||||
do { \
|
do { \
|
||||||
assert((a)->size != 0); \
|
assert((a)->size != 0); \
|
||||||
(a)->size--; \
|
(a)->size--; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sorts the array using qsort()
|
* Sorts the array using qsort()
|
||||||
@@ -192,7 +191,7 @@
|
|||||||
* @param cmp comparator, check qsort() documentation for details
|
* @param cmp comparator, check qsort() documentation for details
|
||||||
*/
|
*/
|
||||||
#define sc_array_sort(a, cmp) \
|
#define sc_array_sort(a, cmp) \
|
||||||
(qsort((a)->elems, (a)->size, sizeof(*(a)->elems), cmp))
|
(qsort((a)->elems, (a)->size, sizeof(*(a)->elems), cmp))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns last element. If array is empty, result is undefined.
|
* Returns last element. If array is empty, result is undefined.
|
||||||
@@ -205,8 +204,8 @@
|
|||||||
* @param elem elem
|
* @param elem elem
|
||||||
*/
|
*/
|
||||||
#define sc_array_foreach(a, elem) \
|
#define sc_array_foreach(a, elem) \
|
||||||
for (size_t _k = 1, _i = 0; _k && _i != (a)->size; _k = !_k, _i++) \
|
for (size_t _k = 1, _i = 0; _k && _i != (a)->size; _k = !_k, _i++) \
|
||||||
for ((elem) = (a)->elems[_i]; _k; _k = !_k)
|
for ((elem) = (a)->elems[_i]; _k; _k = !_k)
|
||||||
|
|
||||||
// (type, name)
|
// (type, name)
|
||||||
sc_array_def(int, int);
|
sc_array_def(int, int);
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ uintptr_t la_symbind64(Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook,
|
|||||||
uintptr_t *defcook, unsigned int *flags,
|
uintptr_t *defcook, unsigned int *flags,
|
||||||
const char *symname) {
|
const char *symname) {
|
||||||
printf("la_symbind64(): symname = %s; sym->st_value = %p\n", symname,
|
printf("la_symbind64(): symname = %s; sym->st_value = %p\n", symname,
|
||||||
(void*)sym->st_value);
|
(void *)sym->st_value);
|
||||||
printf(" ndx = %u; flags = %#x", ndx, *flags);
|
printf(" ndx = %u; flags = %#x", ndx, *flags);
|
||||||
printf("; refcook = %p; defcook = %p\n", refcook, defcook);
|
printf("; refcook = %p; defcook = %p\n", refcook, defcook);
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ Elf64_Addr la_i86_gnu_pltenter(Elf64_Sym *sym, unsigned int ndx,
|
|||||||
uintptr_t *refcook, uintptr_t *defcook,
|
uintptr_t *refcook, uintptr_t *defcook,
|
||||||
La_x86_64_regs *regs, unsigned int *flags,
|
La_x86_64_regs *regs, unsigned int *flags,
|
||||||
const char *symname, long *framesizep) {
|
const char *symname, long *framesizep) {
|
||||||
printf("la_x86_64_gnu_pltenter(): %s (%p)\n", symname, (void*)sym->st_value);
|
printf("la_x86_64_gnu_pltenter(): %s (%p)\n", symname, (void *)sym->st_value);
|
||||||
|
|
||||||
return sym->st_value;
|
return sym->st_value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,9 @@
|
|||||||
#define COMPILATION_H_
|
#define COMPILATION_H_
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *directory;
|
const char *directory;
|
||||||
const char *file;
|
const char *file;
|
||||||
const char *command;
|
const char *command;
|
||||||
} CompileCommand;
|
} CompileCommand;
|
||||||
|
|
||||||
|
|
||||||
#endif // COMPILATION_H_
|
#endif // COMPILATION_H_
|
||||||
|
|||||||
10
src/memory.c
10
src/memory.c
@@ -14,14 +14,16 @@ HiloadResult memory_find_pointer(uptr ptr,
|
|||||||
size_t *index) {
|
size_t *index) {
|
||||||
for (size_t i = 0; i < sc_array_size(regions); i++) {
|
for (size_t i = 0; i < sc_array_size(regions); i++) {
|
||||||
uptr start = regions->elems[i].region_start;
|
uptr start = regions->elems[i].region_start;
|
||||||
// we assume a sorted region by start address, so we can do a quick discard here.
|
// we assume a sorted region by start address, so we can do a quick discard
|
||||||
// very useful for relative vs absolute address checks
|
// here. very useful for relative vs absolute address checks
|
||||||
if (ptr < start) return HILOAD_FAIL;
|
if (ptr < start)
|
||||||
|
return HILOAD_FAIL;
|
||||||
uptr end = regions->elems[i].region_end;
|
uptr end = regions->elems[i].region_end;
|
||||||
if (ptr_in_range(ptr, start, end)) {
|
if (ptr_in_range(ptr, start, end)) {
|
||||||
if (index)
|
if (index)
|
||||||
*index = i;
|
*index = i;
|
||||||
sc_log_debug("Pointer match (%p) found in index: %u, range: %p - %p\n", ptr, i, start, end);
|
sc_log_debug("Pointer match (%p) found in index: %u, range: %p - %p\n",
|
||||||
|
ptr, i, start, end);
|
||||||
return HILOAD_OK;
|
return HILOAD_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/memory.h
11
src/memory.h
@@ -1,9 +1,9 @@
|
|||||||
#ifndef MEMORY_H_
|
#ifndef MEMORY_H_
|
||||||
#define MEMORY_H_
|
#define MEMORY_H_
|
||||||
|
|
||||||
|
#include "array.h"
|
||||||
#include "str.h"
|
#include "str.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "array.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
@@ -24,14 +24,15 @@ typedef struct {
|
|||||||
const char *pathname;
|
const char *pathname;
|
||||||
} MemoryRegion;
|
} MemoryRegion;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
sc_array_def(MemoryRegion, memreg);
|
sc_array_def(MemoryRegion, memreg);
|
||||||
|
|
||||||
/* A pointer that can be used to place the memory regions into. Clears regions before use, but uses the same buffer. */
|
/* A pointer that can be used to place the memory regions into. Clears regions
|
||||||
|
* before use, but uses the same buffer. */
|
||||||
HiloadResult read_memory_maps_self(struct sc_array_memreg *regions);
|
HiloadResult read_memory_maps_self(struct sc_array_memreg *regions);
|
||||||
|
|
||||||
/* Return index the pointer is found in */
|
/* Return index the pointer is found in */
|
||||||
HiloadResult memory_find_pointer(uptr ptr, struct sc_array_memreg* const regions, size_t *index);
|
HiloadResult memory_find_pointer(uptr ptr,
|
||||||
|
struct sc_array_memreg *const regions,
|
||||||
|
size_t *index);
|
||||||
|
|
||||||
#endif // MEMORY_H_
|
#endif // MEMORY_H_
|
||||||
|
|||||||
267
src/str.h
267
src/str.h
@@ -32,100 +32,108 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// string type ----------------------------------------------------------------------------
|
// string type
|
||||||
typedef struct
|
// ----------------------------------------------------------------------------
|
||||||
{
|
typedef struct {
|
||||||
const char* ptr;
|
const char *ptr;
|
||||||
size_t info;
|
size_t info;
|
||||||
} str;
|
} str;
|
||||||
|
|
||||||
// NULL string
|
// NULL string
|
||||||
#define str_null ((str){ 0, 0 })
|
#define str_null ((str){0, 0})
|
||||||
|
|
||||||
// helper macros
|
// helper macros
|
||||||
#define str_ref_info(n) ((n) << 1)
|
#define str_ref_info(n) ((n) << 1)
|
||||||
#define str_owner_info(n) (str_ref_info(n) | 1)
|
#define str_owner_info(n) (str_ref_info(n) | 1)
|
||||||
|
|
||||||
// string properties ----------------------------------------------------------------------
|
// string properties
|
||||||
// length of the string
|
// ---------------------------------------------------------------------- length
|
||||||
static inline
|
// of the string
|
||||||
size_t str_len(const str s) { return s.info >> 1; }
|
static inline size_t str_len(const str s) { return s.info >> 1; }
|
||||||
|
|
||||||
// pointer to the string
|
// pointer to the string
|
||||||
static inline
|
static inline const char *str_ptr(const str s) {
|
||||||
const char* str_ptr(const str s)
|
extern const char *const str_empty_string;
|
||||||
{
|
|
||||||
extern const char* const str_empty_string;
|
|
||||||
|
|
||||||
return s.ptr ? s.ptr : str_empty_string;
|
return s.ptr ? s.ptr : str_empty_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// end of the string
|
// end of the string
|
||||||
static inline
|
static inline const char *str_end(const str s) {
|
||||||
const char* str_end(const str s) { return str_ptr(s) + str_len(s); }
|
return str_ptr(s) + str_len(s);
|
||||||
|
}
|
||||||
|
|
||||||
// test if the string is empty
|
// test if the string is empty
|
||||||
static inline
|
static inline bool str_is_empty(const str s) { return str_len(s) == 0; }
|
||||||
bool str_is_empty(const str s) { return str_len(s) == 0; }
|
|
||||||
|
|
||||||
// test if the string is allocated on the heap
|
// test if the string is allocated on the heap
|
||||||
static inline
|
static inline bool str_is_owner(const str s) { return (s.info & 1) != 0; }
|
||||||
bool str_is_owner(const str s) { return (s.info & 1) != 0; }
|
|
||||||
|
|
||||||
// test if the string is a reference
|
// test if the string is a reference
|
||||||
static inline
|
static inline bool str_is_ref(const str s) { return !str_is_owner(s); }
|
||||||
bool str_is_ref(const str s) { return !str_is_owner(s); }
|
|
||||||
|
|
||||||
// string memory control -------------------------------------------------------------------
|
// string memory control
|
||||||
// free memory allocated for the string
|
// ------------------------------------------------------------------- free
|
||||||
|
// memory allocated for the string
|
||||||
void str_free(const str s);
|
void str_free(const str s);
|
||||||
|
|
||||||
// automatic cleanup
|
// automatic cleanup
|
||||||
void str_free_auto(const str* const ps);
|
void str_free_auto(const str *const ps);
|
||||||
|
|
||||||
#define str_auto str __attribute__((cleanup(str_free_auto)))
|
#define str_auto str __attribute__((cleanup(str_free_auto)))
|
||||||
|
|
||||||
// string movements -----------------------------------------------------------------------
|
// string movements
|
||||||
// free target string, then assign the new value to it
|
// ----------------------------------------------------------------------- free
|
||||||
static inline
|
// target string, then assign the new value to it
|
||||||
void str_assign(str* const ps, const str s) { str_free(*ps); *ps = s; }
|
static inline void str_assign(str *const ps, const str s) {
|
||||||
|
str_free(*ps);
|
||||||
|
*ps = s;
|
||||||
|
}
|
||||||
|
|
||||||
// move the string, resetting the source to str_null
|
// move the string, resetting the source to str_null
|
||||||
static inline
|
static inline str str_move(str *const ps) {
|
||||||
str str_move(str* const ps) { const str t = *ps; *ps = str_null; return t; }
|
const str t = *ps;
|
||||||
|
*ps = str_null;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
// pass ownership of the string
|
// pass ownership of the string
|
||||||
static inline
|
static inline str str_pass(str *const ps) {
|
||||||
str str_pass(str* const ps) { const str t = *ps; ps->info &= ~(size_t)1; return t; }
|
const str t = *ps;
|
||||||
|
ps->info &= ~(size_t)1;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
// swap two string objects
|
// swap two string objects
|
||||||
void str_swap(str* const s1, str* const s2);
|
void str_swap(str *const s1, str *const s2);
|
||||||
|
|
||||||
// string helpers --------------------------------------------------------------------------
|
// string helpers
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
// reset the string to str_null
|
// reset the string to str_null
|
||||||
static inline
|
static inline void str_clear(str *const ps) { str_assign(ps, str_null); }
|
||||||
void str_clear(str* const ps) { str_assign(ps, str_null); }
|
|
||||||
|
|
||||||
// compare two strings lexicographically
|
// compare two strings lexicographically
|
||||||
int str_cmp(const str s1, const str s2);
|
int str_cmp(const str s1, const str s2);
|
||||||
|
|
||||||
// test if two strings match
|
// test if two strings match
|
||||||
static inline
|
static inline bool str_eq(const str s1, const str s2) {
|
||||||
bool str_eq(const str s1, const str s2) { return str_cmp(s1, s2) == 0; }
|
return str_cmp(s1, s2) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
// case-insensitive comparison
|
// case-insensitive comparison
|
||||||
int str_cmp_ci(const str s1, const str s2);
|
int str_cmp_ci(const str s1, const str s2);
|
||||||
|
|
||||||
// case-insensitive match
|
// case-insensitive match
|
||||||
static inline
|
static inline bool str_eq_ci(const str s1, const str s2) {
|
||||||
bool str_eq_ci(const str s1, const str s2) { return str_cmp_ci(s1, s2) == 0; }
|
return str_cmp_ci(s1, s2) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
// test for prefix
|
// test for prefix
|
||||||
bool str_has_prefix(const str s, const str prefix);
|
bool str_has_prefix(const str s, const str prefix);
|
||||||
@@ -133,163 +141,174 @@ bool str_has_prefix(const str s, const str prefix);
|
|||||||
// test for suffix
|
// test for suffix
|
||||||
bool str_has_suffix(const str s, const str suffix);
|
bool str_has_suffix(const str s, const str suffix);
|
||||||
|
|
||||||
// string composition ------------------------------------------------------------------
|
// string composition
|
||||||
|
// ------------------------------------------------------------------
|
||||||
// implementation helpers
|
// implementation helpers
|
||||||
int str_dup_impl(str* const dest, const str s);
|
int str_dup_impl(str *const dest, const str s);
|
||||||
int str_cpy_to_fd(const int fd, const str s);
|
int str_cpy_to_fd(const int fd, const str s);
|
||||||
int str_cpy_to_stream(FILE* const stream, const str s);
|
int str_cpy_to_stream(FILE *const stream, const str s);
|
||||||
|
|
||||||
// copy string
|
// copy string
|
||||||
#define str_cpy(dest, src) \
|
#define str_cpy(dest, src) \
|
||||||
_Generic((dest), \
|
_Generic((dest), \
|
||||||
str*: str_dup_impl, \
|
str*: str_dup_impl, \
|
||||||
int: str_cpy_to_fd, \
|
int: str_cpy_to_fd, \
|
||||||
FILE*: str_cpy_to_stream \
|
FILE*: str_cpy_to_stream \
|
||||||
)((dest), (src))
|
)((dest), (src))
|
||||||
|
|
||||||
// implementation helpers
|
// implementation helpers
|
||||||
int str_cat_range_impl(str* const dest, const str* src, size_t count);
|
int str_cat_range_impl(str *const dest, const str *src, size_t count);
|
||||||
int str_cat_range_to_fd(const int fd, const str* src, size_t count);
|
int str_cat_range_to_fd(const int fd, const str *src, size_t count);
|
||||||
int str_cat_range_to_stream(FILE* const stream, const str* src, size_t count);
|
int str_cat_range_to_stream(FILE *const stream, const str *src, size_t count);
|
||||||
|
|
||||||
// concatenate range of strings
|
// concatenate range of strings
|
||||||
#define str_cat_range(dest, src, count) \
|
#define str_cat_range(dest, src, count) \
|
||||||
_Generic((dest), \
|
_Generic((dest), \
|
||||||
str*: str_cat_range_impl, \
|
str*: str_cat_range_impl, \
|
||||||
int: str_cat_range_to_fd, \
|
int: str_cat_range_to_fd, \
|
||||||
FILE*: str_cat_range_to_stream \
|
FILE*: str_cat_range_to_stream \
|
||||||
)((dest), (src), (count))
|
)((dest), (src), (count))
|
||||||
|
|
||||||
// concatenate string arguments
|
// concatenate string arguments
|
||||||
#define str_cat(dest, ...) \
|
#define str_cat(dest, ...) \
|
||||||
({ \
|
({ \
|
||||||
const str args[] = { __VA_ARGS__ }; \
|
const str args[] = {__VA_ARGS__}; \
|
||||||
str_cat_range((dest), args, sizeof(args)/sizeof(args[0])); \
|
str_cat_range((dest), args, sizeof(args) / sizeof(args[0])); \
|
||||||
})
|
})
|
||||||
|
|
||||||
// implementation helpers
|
// implementation helpers
|
||||||
int str_join_range_impl(str* const dest, const str sep, const str* src, size_t count);
|
int str_join_range_impl(str *const dest, const str sep, const str *src,
|
||||||
int str_join_range_to_fd(const int fd, const str sep, const str* src, size_t count);
|
size_t count);
|
||||||
int str_join_range_to_stream(FILE* const stream, const str sep, const str* src, size_t count);
|
int str_join_range_to_fd(const int fd, const str sep, const str *src,
|
||||||
|
size_t count);
|
||||||
|
int str_join_range_to_stream(FILE *const stream, const str sep, const str *src,
|
||||||
|
size_t count);
|
||||||
|
|
||||||
// join strings around the separator
|
// join strings around the separator
|
||||||
#define str_join_range(dest, sep, src, count) \
|
#define str_join_range(dest, sep, src, count) \
|
||||||
_Generic((dest), \
|
_Generic((dest), \
|
||||||
str*: str_join_range_impl, \
|
str*: str_join_range_impl, \
|
||||||
int: str_join_range_to_fd, \
|
int: str_join_range_to_fd, \
|
||||||
FILE*: str_join_range_to_stream \
|
FILE*: str_join_range_to_stream \
|
||||||
)((dest), (sep), (src), (count))
|
)((dest), (sep), (src), (count))
|
||||||
|
|
||||||
// join string arguments around the separator
|
// join string arguments around the separator
|
||||||
#define str_join(dest, sep, ...) \
|
#define str_join(dest, sep, ...) \
|
||||||
({ \
|
({ \
|
||||||
const str args[] = { __VA_ARGS__ }; \
|
const str args[] = {__VA_ARGS__}; \
|
||||||
str_join_range((dest), (sep), args, sizeof(args)/sizeof(args[0])); \
|
str_join_range((dest), (sep), args, sizeof(args) / sizeof(args[0])); \
|
||||||
})
|
})
|
||||||
|
|
||||||
// constructors ----------------------------------------------------------------------------
|
// constructors
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
// string reference from a string literal
|
// string reference from a string literal
|
||||||
#define str_lit(s) ((str){ "" s, str_ref_info(sizeof(s) - 1) })
|
#define str_lit(s) ((str){"" s, str_ref_info(sizeof(s) - 1)})
|
||||||
|
|
||||||
static inline
|
static inline str str_ref_impl(const str s) {
|
||||||
str str_ref_impl(const str s) { return (str){ s.ptr, s.info & ~(size_t)1 }; }
|
return (str){s.ptr, s.info & ~(size_t)1};
|
||||||
|
}
|
||||||
|
|
||||||
str str_ref_from_ptr(const char* const s);
|
str str_ref_from_ptr(const char *const s);
|
||||||
|
|
||||||
// string reference from anything
|
// string reference from anything
|
||||||
#define str_ref(s) \
|
#define str_ref(s) \
|
||||||
_Generic((s), \
|
_Generic((s), \
|
||||||
str: str_ref_impl, \
|
str: str_ref_impl, \
|
||||||
char*: str_ref_from_ptr, \
|
char*: str_ref_from_ptr, \
|
||||||
const char*: str_ref_from_ptr \
|
const char*: str_ref_from_ptr \
|
||||||
)(s)
|
)(s)
|
||||||
|
|
||||||
// create a reference to the given range of chars
|
// create a reference to the given range of chars
|
||||||
str str_ref_chars(const char* const s, const size_t n);
|
str str_ref_chars(const char *const s, const size_t n);
|
||||||
|
|
||||||
// take ownership of the given range of chars
|
// take ownership of the given range of chars
|
||||||
str str_acquire_chars(const char* const s, const size_t n);
|
str str_acquire_chars(const char *const s, const size_t n);
|
||||||
|
|
||||||
// take ownership of the given string
|
// take ownership of the given string
|
||||||
str str_acquire(const char* const s);
|
str str_acquire(const char *const s);
|
||||||
|
|
||||||
// string from file
|
// string from file
|
||||||
int str_from_file(str* const dest, const char* const file_name);
|
int str_from_file(str *const dest, const char *const file_name);
|
||||||
|
|
||||||
// read maximum nread bytes from file, write bytes read. 0 reads until EOS.
|
// read maximum nread bytes from file, write bytes read. 0 reads until EOS.
|
||||||
int str_from_stream(str* const dest, const char* const file_name, int *nread);
|
int str_from_stream(str *const dest, const char *const file_name, int *nread);
|
||||||
|
|
||||||
// searching and sorting --------------------------------------------------------------------
|
// searching and sorting
|
||||||
// string partitioning (substring search)
|
// -------------------------------------------------------------------- string
|
||||||
bool str_partition(const str src, const str patt, str* const prefix, str* const suffix);
|
// partitioning (substring search)
|
||||||
|
bool str_partition(const str src, const str patt, str *const prefix,
|
||||||
|
str *const suffix);
|
||||||
|
|
||||||
// comparison functions
|
// comparison functions
|
||||||
typedef int (*str_cmp_func)(const void*, const void*);
|
typedef int (*str_cmp_func)(const void *, const void *);
|
||||||
|
|
||||||
int str_order_asc(const void* const s1, const void* const s2);
|
int str_order_asc(const void *const s1, const void *const s2);
|
||||||
int str_order_desc(const void* const s1, const void* const s2);
|
int str_order_desc(const void *const s1, const void *const s2);
|
||||||
int str_order_asc_ci(const void* const s1, const void* const s2);
|
int str_order_asc_ci(const void *const s1, const void *const s2);
|
||||||
int str_order_desc_ci(const void* const s1, const void* const s2);
|
int str_order_desc_ci(const void *const s1, const void *const s2);
|
||||||
|
|
||||||
// sort array of strings
|
// sort array of strings
|
||||||
void str_sort_range(const str_cmp_func cmp, str* const array, const size_t count);
|
void str_sort_range(const str_cmp_func cmp, str *const array,
|
||||||
|
const size_t count);
|
||||||
|
|
||||||
// searching
|
// searching
|
||||||
const str* str_search_range(const str key, const str* const array, const size_t count);
|
const str *str_search_range(const str key, const str *const array,
|
||||||
|
const size_t count);
|
||||||
|
|
||||||
// partitioning
|
// partitioning
|
||||||
size_t str_partition_range(bool (*pred)(const str), str* const array, const size_t count);
|
size_t str_partition_range(bool (*pred)(const str), str *const array,
|
||||||
|
const size_t count);
|
||||||
|
|
||||||
// unique partitioning
|
// unique partitioning
|
||||||
size_t str_unique_range(str* const array, const size_t count);
|
size_t str_unique_range(str *const array, const size_t count);
|
||||||
|
|
||||||
// UTF-32 codepoint iterator ----------------------------------------------------------------
|
// UTF-32 codepoint iterator
|
||||||
|
// ----------------------------------------------------------------
|
||||||
#ifdef __STDC_UTF_32__
|
#ifdef __STDC_UTF_32__
|
||||||
#include <uchar.h>
|
#include <uchar.h>
|
||||||
|
|
||||||
// iterator
|
// iterator
|
||||||
#define for_each_codepoint(var, src) \
|
#define for_each_codepoint(var, src) \
|
||||||
for_each_cp((var), (src), CAT1(inner_it_, __COUNTER__))
|
for_each_cp((var), (src), CAT1(inner_it_, __COUNTER__))
|
||||||
|
|
||||||
// iterator error codes
|
// iterator error codes
|
||||||
#define CPI_END_OF_STRING ((char32_t)-1)
|
#define CPI_END_OF_STRING ((char32_t)-1)
|
||||||
#define CPI_ERR_INCOMPLETE_SEQ ((char32_t)-2)
|
#define CPI_ERR_INCOMPLETE_SEQ ((char32_t)-2)
|
||||||
#define CPI_ERR_INVALID_ENCODING ((char32_t)-3)
|
#define CPI_ERR_INVALID_ENCODING ((char32_t)-3)
|
||||||
|
|
||||||
// implementation
|
// implementation
|
||||||
#define for_each_cp(var, src, it) \
|
#define for_each_cp(var, src, it) \
|
||||||
for(str_cp_iterator it = str_make_cp_iterator(src); (var = str_cp_iterator_next(&it)) <= 0x10FFFFu;)
|
for (str_cp_iterator it = str_make_cp_iterator(src); \
|
||||||
|
(var = str_cp_iterator_next(&it)) <= 0x10FFFFu;)
|
||||||
|
|
||||||
#define CAT1(x, y) CAT2(x, y)
|
#define CAT1(x, y) CAT2(x, y)
|
||||||
#define CAT2(x, y) x ## y
|
#define CAT2(x, y) x##y
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
const char *curr;
|
||||||
const char* curr;
|
const char *const end;
|
||||||
const char* const end;
|
mbstate_t state;
|
||||||
mbstate_t state;
|
|
||||||
} str_cp_iterator;
|
} str_cp_iterator;
|
||||||
|
|
||||||
static inline
|
static inline str_cp_iterator str_make_cp_iterator(const str s) {
|
||||||
str_cp_iterator str_make_cp_iterator(const str s)
|
return (str_cp_iterator){.curr = str_ptr(s), .end = str_end(s)};
|
||||||
{
|
|
||||||
return (str_cp_iterator){ .curr = str_ptr(s), .end = str_end(s) };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char32_t str_cp_iterator_next(str_cp_iterator* const it);
|
char32_t str_cp_iterator_next(str_cp_iterator *const it);
|
||||||
|
|
||||||
#endif // ifdef __STDC_UTF_32__
|
#endif // ifdef __STDC_UTF_32__
|
||||||
|
|
||||||
// tokeniser --------------------------------------------------------------------------------
|
// tokeniser
|
||||||
typedef struct
|
// --------------------------------------------------------------------------------
|
||||||
{
|
typedef struct {
|
||||||
unsigned char bits[32]; // 256 / 8
|
unsigned char bits[32]; // 256 / 8
|
||||||
const char *src, *end;
|
const char *src, *end;
|
||||||
} str_tok_state;
|
} str_tok_state;
|
||||||
|
|
||||||
void str_tok_init(str_tok_state* const state, const str src, const str delim_set);
|
void str_tok_init(str_tok_state *const state, const str src,
|
||||||
bool str_tok(str* const dest, str_tok_state* const state);
|
const str delim_set);
|
||||||
void str_tok_delim(str_tok_state* const state, const str delim_set);
|
bool str_tok(str *const dest, str_tok_state *const state);
|
||||||
|
void str_tok_delim(str_tok_state *const state, const str delim_set);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct sc_array_str names;
|
struct sc_array_str names;
|
||||||
struct sc_array_ptr addresses;
|
struct sc_array_ptr addresses;
|
||||||
@@ -16,7 +15,6 @@ typedef struct {
|
|||||||
|
|
||||||
sc_array_def(SymbolInfos, syms);
|
sc_array_def(SymbolInfos, syms);
|
||||||
|
|
||||||
|
|
||||||
struct dl_phdr_info;
|
struct dl_phdr_info;
|
||||||
struct sc_array_memreg;
|
struct sc_array_memreg;
|
||||||
HiloadResult hi_create_symbol_info(SymbolInfos *,
|
HiloadResult hi_create_symbol_info(SymbolInfos *,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#ifndef TYPES_H_
|
#ifndef TYPES_H_
|
||||||
#define TYPES_H_
|
#define TYPES_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef uint8_t u8;
|
typedef uint8_t u8;
|
||||||
typedef uint16_t u16;
|
typedef uint16_t u16;
|
||||||
|
|||||||
@@ -10,5 +10,5 @@ static int otherValue = 0;
|
|||||||
int getNewValue(int x);
|
int getNewValue(int x);
|
||||||
|
|
||||||
#pragma GCC visibility pop
|
#pragma GCC visibility pop
|
||||||
}
|
} // namespace minimal_lib
|
||||||
#endif // MINIMAL_LIB_H_
|
#endif // MINIMAL_LIB_H_
|
||||||
|
|||||||
Reference in New Issue
Block a user