--
You received this message because you are subscribed to the Google Groups "lua-l" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lua-l+un...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/lua-l/20250830181751.GA1044261%40arraial.inf.puc-rio.br.
To view this discussion visit https://groups.google.com/d/msgid/lua-l/CAN5FJ7eZcr0yFTU76dCNup1g42YCXKWi5biwN2CUuQbH0i04uA%40mail.gmail.com.
Hi Roberto,
Regarding Microsoft Visual Studio/Visual C++. It's technically true that it is not fully C99 compliant. However, in practice it supports all of the C99 features which Lua would require, today, to drop C89 support.
I've been developing various open source projects with MSVC support over the years, starting with VS2008. My experience was that it only really became usable for C99 code with VS2015 which added <stdint.h> and <inttypes.h> and a conforming snprintf; earlier versions lacked the headers but had a non-standard snprint implementation (_snprintf). With VS2019 it gained some more C99 features, maybe some of the string formatting/parsing functions. So for all intents and purposes, with the patches proposed here, Lua will build with VS2022 (confirmed with local and CI testing), and it should also build with VS2019.
Regarding the comments in the thread you linked to (http://lua-users.org/lists/lua-l/2022-11/msg00026.html), the comments Viacheslav Usov made about Visual Studio match what I've said above since he is referring to VS2019 having the needed C99 support. For users who really need to build on older versions, it should be patchable to build back to VS2015 without much effort. IMO anything older than that, which is thoroughly obsolescent for out of support versions of Windows, isn't something that is justifiable for an open source project to spend any time supporting, not least of which are the effort and resources required to test all of these old versions.
Wilfred Nilsen made a comment about embedded systems using old C89 compilers. Historically this was certainly true. Today, I think almost all current parts will have a C99 toolchain provided. I have worked in this field the last 7 years, and I've yet to see a non-C99-conforming compiler. I've used GCC cross-toolchains, IAR (ARM, MSP430), Keil and other less common toolchains, and they all supported C99 without exception. Heck, IAR even supports C++17 with a full embedded C++ standard library, as do the GCC cross-toolchains. While there may still be some vendors who ship ancient compilers, they are a distinct minority, and I don't think it should be used as a justification for keeping Lua stuck on C89. Most parts which have sufficient FLASH and RAM to host a Lua environment will have a C99 toolchain available. One thing which is often lacking in these discussions is concrete detail. Which parts and which compilers are problematic? I acknowledge that such parts must exist, but I've never encountered them personally. I've used MCUs and APs from Atmel, Analog, Nordic, TI, ST and NXP, and never once encounted a problem with C99. And I've run Lua on quite a few of them ;-)
As an example of a previous C99 conversion I did for the libTIFF project in 2021, you might find the context and discussion interesting. This was done in two steps, initially optionally using the C99 headers and features if present, and then as a followup using them unconditionally. The two steps were due to use of Autoconf/CMake and would not apply to Lua--it was primarily for staging the changes for managing the migration, testing and review. I would have liked to have linked to some of the relevant mailing list discussion, but unfortunately the archives went offline for this period.
https://gitlab.com/libtiff/libtiff/-/merge_requests/185 (build system work and preparation; includes detailed toolchain information in the discussion, and built with Linux, Windows (VS2019, Cygwin and MinGW))
https://gitlab.com/libtiff/libtiff/-/merge_requests/205 (main conversion)
https://gitlab.com/libtiff/libtiff/-/merge_requests/?sort=created_date&state=merged&search=c99 (list of small followup changes to complete the migration)
In the patchset I attached I've done a similar migration, but not replaced internal types with standard types e.g. replacement of l_uint32 with uint32_t; there are a number of additional cleanups which could be done as a followup exercise.
Kind regards,
Roger
Yes, certainly. These are just what I have to hand I can recall this evening.
1. The first isn't a Lua problem, it's a bug in the printf implementation of GCC newlib-nano which omits "long long integer" formatting for code size reasons. If you build with the defaults, integers print out "%lld" as "ld" without the number:
random seeds: 1756670153, -2147481100
vs
random seeds: ld, ld
Nothing Lua can reasonably do with this, though basing the default upon e.g. "sizeof(void*)" would give you the native size.
2. The second relates to interoperability with other libraries and the host application.
With the GNU ARM Embedded toolchain (GCC 14.2) building for ARMv8m (Cortex-M33), we have the following typedefs:
uint8 -> unsigned char
uint16_t -> unsigned short
uint32_t -> unsigned long
uint64_t -> unsigned long long
and similarly for the signed variants of each. There is no use of "int" in the fixed-width types. However, if you were to use LUA_32BITS you would get:
#if LUA_32BITS /* { */ /* ** 32-bit integers and 'float' */ #if LUAI_IS32INT /* use 'int' if big enough */ #define LUA_INT_TYPE LUA_INT_INT #else /* otherwise use 'long' */
That is, the Lua 32-bit integer type and the application 32-bit integer type can mismatch. While they are the same size, they are not directly convertible. This then necessitates a lot of typecasts and this is especially problematic with -Wconversion -Werror. Incorrect use of casts could lead to unintentional narrowing. [It's equally annoying with size_t which is "unsigned int" and not uint32_t.]
This is again not strictly a Lua problem--it's an interoperability issue at the boundary between Lua and the host application, including any custom libraries it provides. This is fixable by setting LUA_INT_DEFAULT correctly. But because this is a platform-specific detail, it might then break when you build for a different board with a different processor!
But using the same standard sizes on both sides eliminates the problem entirely.
3. Related to (2), the reliance upon int/long/long long is ambiguous when we don't know what size these are. In quite a few places we are doing quite a bit of work bitshifting to determine how many bits we have to work with. This ambiguity is removed at a stroke by using the fixed-width integer types.
4. Correctness, robustness, safety and static analysis. This was touched on by another poster relating to the use of macros vs inline functions. I'm very interested in improvements which can improve all of these. While this wasn't part of the patchset I sent, it's really doing the groundwork for potential future changes on top of it once C99 is available to be used. Inline functions bring type-safety, are reachable with a debugger, have no added overhead, and are better for static analysis of the codebase. Reducing the number of typecasts also makes it possible to spot problems which are masked, since the static analyser assumes any typecasts you add are correct. This becomes possible when the types are all standard known sizes. And the simplification of the codebase is also a benefit for this as well. Every need for an extra typecase, as mentioned above, is a potential bug which is most likely hidden from static analysis.
Regarding conversions, I actually build Lua with C++17 for the increased stringency around numerical conversions (-DLUA_LANGUAGE_SUPPORT=CXX with the CMake build). And run inline static analysis:
The Lua codebase is of very high quality, so there aren't any serious warnings, but there are a number of suggestions. I had to hunt to find one (minor) potential problem (unreachable code). But if we have to make efforts to verify correctness, C99 is a small step along the way. Internally, I may well be using C++ features such as "constexpr" and "enum class" in addition to inline functions (which have better semantics in C++) to improve the headers and again make compile-time error checking more robust and static analysis more effective. This is likely a much more controversial set of changes to upstream, so I most likely won't do this unless it's wanted! But I can look at making them available for anyone who is interested.
Kind regards,
Roger
2. The second relates to interoperability with other libraries and the host application.
That is, the Lua 32-bit integer type and the application 32-bit integer type can mismatch. While they are the same size, they are not directly convertible. This then necessitates a lot of typecasts and this is especially problematic with -Wconversion -Werror. Incorrect use of casts could lead to unintentional narrowing. [It's equally annoying with size_t which is "unsigned int" and not uint32_t.]
3. Related to (2), the reliance upon int/long/long long is ambiguous when we don't know what size these are. In quite a few places we are doing quite a bit of work bitshifting to determine how many bits we have to work with. This ambiguity is removed at a stroke by using the fixed-width integer types.
long on the other side is typically ALWAYS 32bit as I would assume... I hope I am correct :).