diff --git a/firmware/include/string-extra.h b/firmware/include/string-extra.h index 6a9e0c77be..9ab53d8154 100644 --- a/firmware/include/string-extra.h +++ b/firmware/include/string-extra.h @@ -34,4 +34,38 @@ #endif #endif +/* copies a buffer of len bytes and null terminates it */ +static inline char * strmemcpy(char *dst, const char *src, size_t len) +{ + /* NOTE: for now, assumes valid parameters! */ + *(char *)mempcpy(dst, src, len) = '\0'; + return dst; +} + +/* duplicate and null-terminate a memory block on the stack with alloca() */ +#define strmemdupa(s, l) \ + ({ const char *___s = (s); \ + size_t ___l = (l); \ + char *___buf = alloca(___l + 1); \ + strmemcpy(___buf, ___s, ___l); }) + +/* strdupa and strndupa may already be provided by a system's string.h */ + +#ifndef strdupa +/* duplicate an entire string on the stack with alloca() */ +#define strdupa(s) \ + ({ const char *__s = (s); \ + strmemdupa((__s), strlen(__s)); }) +#endif /* strdupa */ + +#ifndef strndupa +/* duplicate a string on the stack with alloca(), truncating it if it is too + long */ +#define strndupa(s, n) \ + ({ const char *__s = (s); \ + size_t __n = (n); \ + size_t __len = strlen(_s); \ + strmemdupa(__s, MIN(__n, __len)); }) +#endif /* strndupa */ + #endif /* STRING_EXTRA_H */ diff --git a/firmware/libc/include/stdlib.h b/firmware/libc/include/stdlib.h index 57553367c4..e24d6a579f 100644 --- a/firmware/libc/include/stdlib.h +++ b/firmware/libc/include/stdlib.h @@ -31,6 +31,11 @@ void free(void *); void *realloc(void *, size_t); int atexit(void (*)(void)); +#ifdef __GNUC__ +# undef alloca +# define alloca(size) __builtin_alloca (size) +#endif /* GCC. */ + #define RAND_MAX INT_MAX void srand(unsigned int seed); diff --git a/firmware/target/hosted/system-hosted.h b/firmware/target/hosted/system-hosted.h index e60803fde0..5e7a7d7d99 100644 --- a/firmware/target/hosted/system-hosted.h +++ b/firmware/target/hosted/system-hosted.h @@ -22,7 +22,7 @@ #ifndef __SYSTEM_HOSTED_H__ #define __SYSTEM_HOSTED_H__ -#include "system.h" +#ifndef __PCTOOL__ static inline void commit_dcache(void) {} static inline void commit_discard_dcache(void) {} @@ -34,4 +34,14 @@ static inline void core_sleep(void) wait_for_interrupt(); } +#endif /* __PCTOOL__ */ + +#if defined(WIN32) || defined(__PCTOOL__) + +#ifndef alloca +#define alloca __builtin_alloca +#endif + +#endif /* WIN32 || __PCTOOL__ */ + #endif