WCharacter.h - isascii not declared in this scope on arm-none-eabi
WCharacter.h use isascii, but isascii not defined by the ANSI C standard.
Note: To fix for arm-none-eabi platform you can add definition:
#define _GNU_SOURCE
Can you please elaborate in which use case you experience which problem, preferable with a pull request to show mitigation of the issue?
I develop arduino core for Cortex M4 microcontroller and use standard toolchain arm-none-eabi which have't definnition isascii() ,because isascii() not defined by the ANSI C standard.
There are 2 ways to resolve problem:
- Api user is adding definition
_GNU_SOURCEtoplatform.txt isascii()replaced by((c & ~0x7f) != 0 ? false : true);in WCharacter.h#L66
I was facing similar issues using WCharacter.h and would like to ask if there's any fix for this planned? Perhaps remove the undefined functions?
A fix to this issue is critical for my project: https://github.com/zephyrproject-rtos/gsoc-2022-arduino-core which currently just deletes WCharacter.h as a hack.
@DhruvaG2000 could you test if the information in this page also applies to embedded toolchains?
If enclosing the isascii() call between #if definded(_XOPEN_SOURCE) || defined(_DEFAULT_SOURCE) || defined(_SVID_SOURCE) works I'd go in that direction.
The alternative implementation provided by @kenny5660 looks correct but I found this example that seems to contadict everything I know about ascii :exploding_head:
Note: To fix for arm-none-eabi platform you can add definition: #define _GNU_SOURCE
Note that this will not work, since the user might have included libc headers before WCharacter.h is included. Adding it to platform.txt like @kenny5660 suggests later would work as expected.
However, I'm not entirely sure what further implications defining _GNU_SOURCE has, so maybe it should be used with caution, and maybe just inlining isascii() as per @kenny5660 second suggestion could be preferred?
As for the proposed implementation, that seems to be identical to the glibc version:
#define __isascii(c) (((c) & ~0x7f) == 0) /* If C is a 7 bit value. */
And effectively the same (but written differently) as the newlib version (which is wat the arm gcc build uses):
return c >= 0 && c< 128;
It also is what POSIX specifies: https://pubs.opengroup.org/onlinepubs/9699919799/functions/isascii.html
So I guess the IBM link that @facchinm posted is just weird, since it treats 0x81 and above as valid ASCII, which does not look standards-compliant to me. So let's ignore that.
If enclosing the isascii() call between #if definded(_XOPEN_SOURCE) || defined(_DEFAULT_SOURCE) || defined(_SVID_SOURCE) works I'd go in that direction.
You mean that if those are defined, use isascii() and if not, use our own implementation? Or omit isAscii() entirely?
You mean that if those are defined, use isascii() and if not, use our own implementation
yes, something like that, but if we take the "trivial" implementation we can just replace it for all the platforms
To be specific, there are the set of errors I get when trying to build with my zephyr project:
/home/dhruva/zephyrproject/modules/lib/gsoc-2022-arduino-core/cores/arduino/./api/WCharacter.h: In function 'bool arduino::isAscii(int)':
/home/dhruva/zephyrproject/modules/lib/gsoc-2022-arduino-core/cores/arduino/./api/WCharacter.h:66:12: error: 'isascii' was not declared in this scope; did you mean 'isAscii'?
66 | return ( isascii (c) == 0 ? false : true);
| ^~~~~~~
| isAscii
/home/dhruva/zephyrproject/modules/lib/gsoc-2022-arduino-core/cores/arduino/./api/WCharacter.h: In function 'int arduino::toAscii(int)':
/home/dhruva/zephyrproject/modules/lib/gsoc-2022-arduino-core/cores/arduino/./api/WCharacter.h:148:10: error: 'toascii' was not declared in this scope; did you mean 'toAscii'?
148 | return toascii (c);
| ^~~~~~~
| toAscii
Compiler being used is: zephyr-sdk-0.14.2/arm-zephyr-eabi/bin/arm-zephyr-eabi-g++ and it is configured to enable newlibc usage.
Without newlibc there are many more errors.
I've also encountered this issue during the creation of a custom Arduino Core.
As already discussed here, in newlib this function is compiled when _GNU_SOURCE is defined (which sets _DEFAULT_SOURCE, which in turn sets __MISC_VISIBLE):
https://github.com/bminor/newlib/blob/34876c05a527a7295920979fce69cec6b4cb613c/newlib/libc/include/ctype.h#L31-L33
Setting the -D_GNU_SOURCE compiler flag seems to work, but adding a custom implementation of isascii and toascii, might be safer if we don't know the full impact of enabling _GNU_SOURCE.
Checking in to see if this being tracked as an issue by the team - is this something we can plan to be fixed in an upcoming release? 🙏
The "many more errors" I said above are the following: (building without newlibc)
66 | return ( isascii (c) == 0 ? false : true);
| ^~~~~~~
| isAscii
/home/dgole/zephyrproject/modules/lib/Arduino-Zephyr-API/cores/arduino/./api/WCharacter.h: In function 'bool arduino::isWhitespace(int)':
/home/dgole/zephyrproject/modules/lib/Arduino-Zephyr-API/cores/arduino/./api/WCharacter.h:73:12: error: 'isblank' was not declared in this scope
73 | return ( isblank (c) == 0 ? false : true);
| ^~~~~~~
/home/dgole/zephyrproject/modules/lib/Arduino-Zephyr-API/cores/arduino/./api/WCharacter.h: In function 'bool arduino::isLowerCase(int)':
/home/dgole/zephyrproject/modules/lib/Arduino-Zephyr-API/cores/arduino/./api/WCharacter.h:101:11: error: 'islower' was not declared in this scope; did you mean 'tolower'?
101 | return (islower (c) == 0 ? false : true);
| ^~~~~~~
| tolower
/home/dgole/zephyrproject/modules/lib/Arduino-Zephyr-API/cores/arduino/./api/WCharacter.h: In function 'bool arduino::isPunct(int)':
/home/dgole/zephyrproject/modules/lib/Arduino-Zephyr-API/cores/arduino/./api/WCharacter.h:116:12: error: 'ispunct' was not declared in this scope; did you mean 'isPunct'?
116 | return ( ispunct (c) == 0 ? false : true);
| ^~~~~~~
| isPunct
/home/dgole/zephyrproject/modules/lib/Arduino-Zephyr-API/cores/arduino/./api/WCharacter.h: In function 'int arduino::toAscii(int)':
/home/dgole/zephyrproject/modules/lib/Arduino-Zephyr-API/cores/arduino/./api/WCharacter.h:148:10: error: 'toascii' was not declared in this scope; did you mean 'toAscii'?
148 | return toascii (c);
| ^~~~~~~
| toAscii