Skip to content

Transition to C99#942

Open
JohnoKing wants to merge 4 commits intoksh93:devfrom
JohnoKing:require-c99
Open

Transition to C99#942
JohnoKing wants to merge 4 commits intoksh93:devfrom
JohnoKing:require-c99

Conversation

@JohnoKing
Copy link
Copy Markdown

@JohnoKing JohnoKing commented Mar 9, 2026

This commit is a compilation of many old patches of mine. It removes obsolete code and enforces C99 as a build requirement.

Changes:

  • Remove many unused tests and useless feature tests. (This was a bit more involved for <sys/types.h>, which had annoying special casing.) This included the "check for global headers" in the iffe script.
  • Assume fchmod is present and use it instead of chmod in shcomp for very slightly better performance.
  • dotpaths_lib(): Use fstat rather than stat for the PWD for better performance.
  • Scrap pre-C99 fallbacks for iswblank(3).
  • Replaced usage of the obsolescent timeofday() macro with the more portable tvgettime() function in libast, which itself uses the modern clock_gettime internally when it's available.
  • Replaced usage of strcopy with either strcpy or stpcpy in cases where no buffer overlap occurs. There are perhaps more places where replacement is possible (ksh93v- and ksh2020 do this far more liberally), but I'm trying to be conservative with these changes to avoid accidentally introducing bugs.
  • Replaced an instance of strncopy with strlcpy in keytrap() because the buffers don't overlap.
  • Add pertinent documentation as it relates to str*copy's usage with overlapping buffers.
  • Backported a modified version of ksh93v-'s stpcpy fallback.
  • Introduced usage of C99 restrict, primarily for standards compliance in compatibility functions (though some regular functions like sfopen() will also use restrict now).
  • Assume C99 __func__ is available and drop now unnecessary C90 feature tests.
  • Added a few casts to fix some compiler warnings.
  • Remove basic iffe probes for various C99 multibyte functions (excluding those that still need tests due to platform-specific bugs). Also removed other unnecessary probes for C99 and POSIX functionality.
  • Remove unnecessary mktime.c, wc.c and wordexp.c compat files (the operating system should provide these functions).
  • Switched to using C99-style struct init throughout the codebase.
  • Removed usage of bzero, bcopy, memclear and memzero in favor of standard memset and memcpy.
  • Minor bugfix: avoid passing overlapping buffers to getaddrinfo in io.c because that violates the POSIX standard.
  • make.probe: Automatically use the latest C standard available (i.e. C23) because GCC/Clang may use something older by default whilst having support for newer standards.

I have additional changes for using C99-style for loops and bools, but those have been excluded because this patch is big enough as it is. I also encountered crashing bugs when I attempted to remove widespread usage of the struct hack, so the struct hack was only removed if it was already disabled by a preexisting __STDC_VERSION__ check.

Progresses #777 (this commit doesn't include or fix the removed _c99_in_the_wild code).

@JohnoKing JohnoKing changed the title C99 transition Transition to C99 Mar 9, 2026
This commit is a compilation of many old patches of mine.
It removes obsolete code and enforces C99 as a build
requirement.

Changes:
- Remove many unused tests and useless feature tests.
  (This was a bit more involved for <sys/types.h>, which
  had annoying special casing.) This included the
  'check for global headers' in the iffe script.
- Assume fchmod is present and use it instead of chmod in
  shcomp for slightly better performance.
- dotpaths_lib(): Use fstat rather than stat for the PWD
  for better performance.
- Scrap pre-C99 fallbacks for iswblank(3).
- Replaced usage of the obsolescent timeofday() macro with the
  more portable tvgettime() function in libast, which itself uses
  the modern clock_gettime internally.
- Replaced usage of strcopy with either strcpy or stpcpy in
  cases where no buffer overlap occurs. There are perhaps
  more places where replacement is possible (ksh93v- and ksh2020
  do this far more liberally), but I'm trying to be conservative
  with these changes to avoid accidentally introducing bugs.
- Replaced an instance of strncopy with strlcpy in keytrap()
  because the buffers don't overlap.
  - Also replaced some instances of strncpy with strlcpy
    (vide att#266 and f63ebd0).
- Add pertinent documentation as it relates to str*copy's
  usage with overlapping buffers.
- Backported a modified version of ksh93v-'s stpcpy fallback.
- Introduced usage of C99 restrict, primarily for standards
  compliance in compatibility functions (though some regular
  functions like sfopen() do also use restrict now).
- Assume C99 __func__ is available and drop now unneeded
  C90 feature tests.
- Added a few casts to fix some compiler warnings.
- Remove basic iffe probes for various C99 multibyte functions
  (excluding those that still need tests due to platform-specific
  bugs). Also removed other unnecessary probes for C99 and POSIX
  functionality.
- Remove unnecessary mktime.c, wc.c and wordexp.c compat files
  (the operating system should provide these functions).
- Switched to using C99-style struct init throughout the codebase.
- Removed usage of bzero, bcopy, memclear and memzero in favor
  of ISO C memset and memcpy.
- make.probe: Automatically use the latest C standard available
  (i.e. C23) because GCC/Clang may use something older by default
  whilst having support for newer standards.

I have additional changes for using C99-style for loops and bools,
but those have been excluded because this patch is big enough as it is.

Progresses ksh93#777
(This commit doesn't include or fix the removed _c99_in_the_wild code.)
@McDutchie
Copy link
Copy Markdown

I have additional changes for using C99-style for loops and bools, but those have been excluded because this patch is big enough as it is.

I would also like to think about/discuss this some more before committing to these, because so far I'm failing to see an actual advantage to either of these.

I quite like the C90 norm that all variables are declared at the beginning of each braces block that they're scoped to; it's good for clarity, IMHO.

As for bools, are they really any more than syntactic sugar? I could be missing something, e.g., do they improve performance? If not, I don't feel the need for them.

@McDutchie
Copy link
Copy Markdown

Alright, I think we're going to a need C99 flexible struct member to fix the alignment issue in #964 without more hackery. So, it's time for this.

@McDutchie
Copy link
Copy Markdown

Unfortunately, the PR doesn't build on macOS.

# src/lib/libast/Mamfile: 2305-2311: make strntold.o
+ compile /usr/local/src/ksh93/ksh/src/lib/libast/string/strntold.c -Iport -I/usr/local/src/ksh93/ksh/src/lib/libast/port -Isfio -I/usr/local/src/ksh93/ksh/src/lib/libast/sfio
+ s=/usr/local/src/ksh93/ksh/src/lib/libast/string/strntold.c
+ shift
+ cc -D_BLD_ast '-std=gnu23' -O0 -g -Wall -funsigned-char -fno-strict-aliasing -I. -I/usr/local/src/ksh93/ksh/src/lib/libast -Icomp -I/usr/local/src/ksh93/ksh/src/lib/libast/comp -Iport -I/usr/local/src/ksh93/ksh/src/lib/libast/port -Isfio -I/usr/local/src/ksh93/ksh/src/lib/libast/sfio -Iinclude -I/usr/local/src/ksh93/ksh/src/lib/libast/include -Istd -I/usr/local/src/ksh93/ksh/src/lib/libast/std -c /usr/local/src/ksh93/ksh/src/lib/libast/string/strntold.c
In file included from /usr/local/src/ksh93/ksh/src/lib/libast/string/strntold.c:29:
/usr/local/src/ksh93/ksh/src/lib/libast/sfio/sfstrtof.h:160:1: error: conflicting types for 'strntold'
  160 | S2F_function(const char* str, size_t size, char** end)
      | ^
/usr/local/src/ksh93/ksh/src/lib/libast/string/strntold.c:25:22: note: expanded from macro 'S2F_function'
   25 | #define S2F_function    strntold
      |                         ^
/usr/local/src/ksh93/ksh/src/lib/libast/include/ast.h:378:20: note: previous declaration is here
  378 | extern long double      strntold(const char*, size_t, char**);
      |                         ^
1 error generated.
mamake [lib/libast]: *** exit code 1 making strntold.o
mamake: *** exit code 1 making lib/libast
mamake: *** exit code 1 making all
package: make failed at Sat Apr  4 22:13:28 BST 2026 in /usr/local/src/ksh93/ksh/arch/darwin.arm64-64,d

@JohnoKing
Copy link
Copy Markdown
Author

JohnoKing commented Apr 4, 2026

I quite like the C90 norm that all variables are declared at the beginning of each braces block that they're scoped to; it's good for clarity, IMHO.

As for bools, are they really any more than syntactic sugar? I could be missing something, e.g., do they improve performance? If not, I don't feel the need for them.

Local variables in for loops via for(int i = 0; etc) and bools are ultimately secondary, being primarily useful for readability (the former helps with large functions that repeatedly use an i variable, since it can be unclear whether the value is actually used outside of the loop if the function is exceedingly long).
I primarily want to utilize C99's restrict, struct initializers and (for a later PR) variadic macros.

Unfortunately, the PR doesn't build on macOS.

I don't have anything running macOS, but perhaps that's caused by sfstrtof.h using double instead of long double. Test patch:

--- a/src/lib/libast/sfio/sfstrtof.h
+++ b/src/lib/libast/sfio/sfstrtof.h
@@ -59,11 +59,6 @@
 #endif
 #endif
 
-#if S2F_type == 2 && _ast_fltmax_double
-#undef	S2F_type
-#define S2F_type	1
-#endif
-
 #if S2F_type == 0
 #define S2F_number	float
 #define S2F_ldexp	ldexp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants