Skip to content

Commit 487d801

Browse files
Replace _P macros with inline functions
Previously, functions like memcpy_P were replaced by their non-progmem version using macros. However, these macros added a :: prefix, presumably to allow e.g. memcpy_P to be used in a context where a (namespace or class) local version of memcpy is defined. Adding the :: makes sure the global version is used. However, if the actual invocation of e.g. memcpy_P also uses this prefix (e.g. `return ::memcpy_P(...)`, to disambiguate when a local version of `memcpy_P` is also defined), this results in a double prefix and compilation failure. To fix this, this commit replaces the wrapper macros with inline functions that call the non-progmem version normally. These inline functions were mostly mechanically generated from the original avr/pgmspace.h documentation, removing some AVR-specific functions that do not have a standard equivalent and adding som casts here and there (where the progmem version returns `char*` and the regular version `const char*`).
1 parent 4ca5e76 commit 487d801

File tree

1 file changed

+51
-43
lines changed

1 file changed

+51
-43
lines changed

Diff for: cpp/arduino/avr/pgmspace.h

+51-43
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ out.each { |l| puts d(l) }
1515
*/
1616

1717
#include <string.h>
18+
#include <stdint.h>
1819

1920
#define PROGMEM
2021

@@ -26,6 +27,11 @@ out.each { |l| puts d(l) }
2627
#define PGM_VOID_P const void *
2728
#endif
2829

30+
// These are normally 32-bit, but here use (u)intptr_t to ensure a pointer can
31+
// always be safely cast to these types.
32+
typedef intptr_t int_farptr_t;
33+
typedef uintptr_t uint_farptr_t;
34+
2935
// everything's a no-op
3036
#define PSTR(s) ((const char *)(s))
3137

@@ -49,46 +55,48 @@ out.each { |l| puts d(l) }
4955

5056
#define pgm_get_far_address(var) ( (uint_farptr_t) (&(var)) )
5157

52-
#define memchr_P(...) ::memchr(__VA_ARGS__)
53-
#define memcmp_P(...) ::memcmp(__VA_ARGS__)
54-
#define memccpy_P(...) ::memccpy(__VA_ARGS__)
55-
#define memcpy_P(...) ::memcpy(__VA_ARGS__)
56-
#define memmem_P(...) ::memmem(__VA_ARGS__)
57-
#define memrchr_P(...) ::memrchr(__VA_ARGS__)
58-
#define strcat_P(...) ::strcat(__VA_ARGS__)
59-
#define strchr_P(...) ::strchr(__VA_ARGS__)
60-
#define strchrnul_P(...) ::strchrnul(__VA_ARGS__)
61-
#define strcmp_P(...) ::strcmp(__VA_ARGS__)
62-
#define strcpy_P(...) ::strcpy(__VA_ARGS__)
63-
#define strcasecmp_P(...) ::strcasecmp(__VA_ARGS__)
64-
#define strcasestr_P(...) ::strcasestr(__VA_ARGS__)
65-
#define strcspn_P(...) ::strcspn(__VA_ARGS__)
66-
#define strlcat_P(...) ::strlcat(__VA_ARGS__)
67-
#define strlcpy_P(...) ::strlcpy(__VA_ARGS__)
68-
#define strnlen_P(...) ::strnlen(__VA_ARGS__)
69-
#define strncmp_P(...) ::strncmp(__VA_ARGS__)
70-
#define strncasecmp_P(...) ::strncasecmp(__VA_ARGS__)
71-
#define strncat_P(...) ::strncat(__VA_ARGS__)
72-
#define strncpy_P(...) ::strncpy(__VA_ARGS__)
73-
#define strpbrk_P(...) ::strpbrk(__VA_ARGS__)
74-
#define strrchr_P(...) ::strrchr(__VA_ARGS__)
75-
#define strsep_P(...) ::strsep(__VA_ARGS__)
76-
#define strspn_P(...) ::strspn(__VA_ARGS__)
77-
#define strstr_P(...) ::strstr(__VA_ARGS__)
78-
#define strtok_P(...) ::strtok(__VA_ARGS__)
79-
#define strtok_P(...) ::strtok(__VA_ARGS__)
80-
#define strlen_P(...) ::strlen(__VA_ARGS__)
81-
#define strnlen_P(...) ::strnlen(__VA_ARGS__)
82-
#define memcpy_P(...) ::memcpy(__VA_ARGS__)
83-
#define strcpy_P(...) ::strcpy(__VA_ARGS__)
84-
#define strncpy_P(...) ::strncpy(__VA_ARGS__)
85-
#define strcat_P(...) ::strcat(__VA_ARGS__)
86-
#define strlcat_P(...) ::strlcat(__VA_ARGS__)
87-
#define strncat_P(...) ::strncat(__VA_ARGS__)
88-
#define strcmp_P(...) ::strcmp(__VA_ARGS__)
89-
#define strncmp_P(...) ::strncmp(__VA_ARGS__)
90-
#define strcasecmp_P(...) ::strcasecmp(__VA_ARGS__)
91-
#define strncasecmp_P(...) ::strncasecmp(__VA_ARGS__)
92-
#define strstr_P(...) ::strstr(__VA_ARGS__)
93-
#define strlcpy_P(...) ::strlcpy(__VA_ARGS__)
94-
#define memcmp_P(...) ::memcmp(__VA_ARGS__)
58+
inline const void * memchr_P(const void *s, int val, size_t len) { return memchr(s, val, len); }
59+
inline int memcmp_P(const void *s1, const void *s2, size_t len) { return memcmp(s1, s2, len); }
60+
inline void *memccpy_P(void *dest, const void *src, int val, size_t len) { return memccpy(dest, src, val, len); }
61+
inline void *memcpy_P(void *dest, const void *src, size_t n) { return memcpy(dest, src, n); }
62+
inline void *memmem_P(const void *s1, size_t len1, const void *s2, size_t len2) { return memmem(s1, len1, s2, len2); }
63+
inline const void *memrchr_P(const void *src, int val, size_t len) { return memrchr(src, val, len); }
64+
inline char *strcat_P(char *dest, const char *src) { return strcat(dest, src); }
65+
inline const char *strchr_P(const char *s, int val) { return strchr(s, val); }
66+
inline const char *strchrnul_P(const char *s, int c) { return strchrnul(s, c); }
67+
inline int strcmp_P(const char *s1, const char *s2) { return strcmp(s1, s2); }
68+
inline char *strcpy_P(char *dest, const char *src) { return strcpy(dest, src); }
69+
inline int strcasecmp_P(const char *s1, const char *s2) { return strcasecmp(s1, s2); }
70+
inline char *strcasestr_P(const char *s1, const char *s2) { return (char*)strcasestr(s1, s2); }
71+
inline size_t strcspn_P(const char *s, const char *reject) { return strcspn(s, reject); }
72+
// strlcat and strlcpy are AVR-specific and not entirely trivial to reimplement using strncat it seems
73+
//inline size_t strlcat_P(char *dst, const char *src, size_t siz) { return strlcat(dst, src, siz); }
74+
//inline size_t strlcpy_P(char *dst, const char *src, size_t siz) { return strlcpy(dst, src, siz); }
75+
//inline size_t strlcat_PF(char *dst, uint_farptr_t src, size_t n) { return strlcat(dst, (const char*)src, n); }
76+
//inline size_t strlcpy_PF(char *dst, uint_farptr_t src, size_t siz) { return strlcpy(dst, (const char*)src, siz); }
77+
inline size_t strnlen_P(const char *src, size_t len) { return strnlen(src, len); }
78+
inline int strncmp_P(const char *s1, const char *s2, size_t n) { return strncmp(s1, s2, n); }
79+
inline int strncasecmp_P(const char *s1, const char *s2, size_t n) { return strncasecmp(s1, s2, n); }
80+
inline char *strncat_P(char *dest, const char *src, size_t len) { return strncat(dest, src, len); }
81+
inline char *strncpy_P(char *dest, const char *src, size_t n) { return strncpy(dest, src, n); }
82+
inline char *strpbrk_P(const char *s, const char *accept) { return (char*)strpbrk(s, accept); }
83+
inline const char *strrchr_P(const char *s, int val) { return strrchr(s, val); }
84+
inline char *strsep_P(char **sp, const char *delim) { return strsep(sp, delim); }
85+
inline size_t strspn_P(const char *s, const char *accept) { return strspn(s, accept); }
86+
inline char *strstr_P(const char *s1, const char *s2) { return (char*)strstr(s1, s2); }
87+
inline char *strtok_P(char *s, const char * delim) { return strtok(s, delim); }
88+
inline char *strtok_r_P(char *string, const char *delim, char **last) { return strtok_r(string, delim, last); }
89+
inline size_t strlen_PF(uint_farptr_t s) { return strlen((char*)s); }
90+
inline size_t strnlen_P(uint_farptr_t s, size_t len) { return strnlen((char*)s, len); }
91+
inline void *memcpy_PF(void *dest, uint_farptr_t src, size_t n) { return memcpy(dest, (const char*)src, n); }
92+
inline char *strcpy_PF(char *dst, uint_farptr_t src) { return strcpy(dst, (const char*)src); }
93+
inline char *strncpy_PF(char *dst, uint_farptr_t src, size_t n) { return strncpy(dst, (const char*)src, n); }
94+
inline char *strcat_PF(char *dst, uint_farptr_t src) { return strcat(dst, (const char*)src); }
95+
inline char *strncat_PF(char *dst, uint_farptr_t src, size_t n) { return strncat(dst, (const char*)src, n); }
96+
inline int strcmp_PF(const char *s1, uint_farptr_t s2) { return strcmp(s1, (const char*)s2); }
97+
inline int strncmp_PF(const char *s1, uint_farptr_t s2, size_t n) { return strncmp(s1, (const char*)s2, n); }
98+
inline int strcasecmp_PF(const char *s1, uint_farptr_t s2) { return strcasecmp(s1, (const char*)s2); }
99+
inline int strncasecmp_PF(const char *s1, uint_farptr_t s2, size_t n) { return strncasecmp(s1, (const char*)s2, n); }
100+
inline char *strstr_PF(const char *s1, uint_farptr_t s2) { return (char*)strstr(s1, (const char*)s2); }
101+
inline int memcmp_PF(const void *s1, uint_farptr_t s2, size_t len) { return memcmp(s1, (const char*)s2, len); }
102+
inline size_t strlen_P(const char *src) { return strlen(src); }

0 commit comments

Comments
 (0)