WIP: Implement freestanding C memory and string primitives #3

Draft
erikinkinen wants to merge 6 commits from feature/posix-compat into main
Owner

Summary and rationale

Provide eighteen freestanding C byte and string operations through documented Rust declarations, partial C headers and one explicitly selected assembler companion. Add strnlen, which stops at the first NUL or the caller's full-width bound. Preserve all seventeen preceding function bodies.

Tracking and scope

  • C runtime/libc design: #1; authority and quality audit: #2.
  • Signed source: bdcbbea43550e8b99cd9a8221e4bc5a645637990 on feature/posix-compat.
  • Partial x86_64 SysV ELF object/archive and dependency-free no_std Rust interface. Startup, allocation, errno storage, remaining functions, POSIX adapters and full guest builds remain open.
  • The original Integration process helper remains pinned to e2b1cf5995bcf6334839cda9a013e90fa97787d5.

Architecture, authority and failure behavior

For a positive bound, strnlen requires initialized readable bytes through the first NUL or the complete bound, whichever comes first. It returns that NUL's index or the bound. No byte at the bound or after NUL is read, and the source cursor is not advanced after the last permitted byte. Count and return value retain the full 64-bit width. Only the namespaced raw zero-count interface expressly permits null; conventional C pointer rules remain applicable.

The scalar leaf uses no stack scratch, allocation, syscall, errno access or shared state. It obtains no capabilities and retains no pointer. The returned count grants no memory access. Review removed a redundant loop comparison while preserving the pre-read and exhausted-bound checks; no measured speedup is claimed.

Core/public/hidden policies share the same eighteen bodies. The query section is 178 bytes and preserves the original 152-byte prefix; the 234-byte memory, 136-byte writer and 344-byte span sections remain exact. Eight assembler source roles include zero-instruction alias files under every policy. Consumers must explicitly select the new revision and bytes. Missing or duplicate companions fail linkage. Receipts bind selected inputs without establishing repository provenance or the complete installed compiler closure.

Validation evidence

Matching Docs 7ccbe0bfa83ce5942878fb7cf8c57bb1abe75d00 is signed and pushed in Docs PR #4. Its original-source references select ABI 2417b283 and eighteen-function libc bdcbbea, with 161 and twenty API routes respectively. All 44 documentation tests, both API checks and 55 Markdown files pass. The complete 2,339-page manual passes in 154.64 seconds with zero final warnings; all 425,255 word boxes fit and nine actual previews pass visual review. The first render was interrupted by an outer watchdog that could not observe the inner log; its failed statuses and clean cleanup are retained. The corrected outer budget preserves the inner hard/progress limits, and passing API/unit checks were reused. Matching Docs push CI 837 and PR CI 838 both pass for signed 7ccbe0bfa83ce5942878fb7cf8c57bb1abe75d00, ending by 05:58:35 UTC on September 14. All four complete logs total 752,104 bytes and are correlated with the original workflow and build/publish scripts. Each manual job passes 44 tests and finishes at 2,339 pages with zero final-pass warnings; thirty first-pass and one second-pass convergence warnings resolve. Each Markdown job checks 55 files with zero errors. The logged CI PDF size is 4,105,617 bytes; CI artifact bytes and geometry were not independently inspected. Local layout and visual evidence remain separate. This adds no native metadata operation, companion migration or complete guest build result.

Selected Rust 1.97.1 formatting, strict Clippy, warning-denied host/freestanding builds and private rustdoc pass. Each default/all-feature debug/release host invocation passes 33 Rust tests, for 132 executions. The feature set contains only empty default; those commands have identical effective features. Rust crate roots deny missing documentation.

All 90 independent array cases, 23 producer controls and twelve mixed C/Rust programs pass. New witnesses cover all byte values, alignments, exact nonterminated bounds, read-only protected-page edges, early NUL and real callbacks with pointer/count arguments after six scalar register arguments. Large bounds over short terminated strings test argument width, not returned lengths above 2^32. Existing register, direction-flag and guarded-stack checks remain. Forty intentional link rejections cover missing, duplicate and older companions; the isolated old-seventeen control requires exactly the two new strnlen symbol names, preserving the earlier writer/span controls.

All recorded object/archive outputs and original instruction witnesses correlate. Nine Markdown files, workflow shell syntax, canonical documents, source consistency, whitespace and code-size checks pass. The runtime matrix and dependent finishing checks complete without an unexpected failure or warning. A later ROADMAP-only result update receives the affected documentation/source checks without runtime replay.

Push CI 11 and PR CI 12 both pass for signed bdcbbea, ending by 05:40:42 UTC on September 13. All four complete logs are retained (64,532 bytes), with no compiler or lint warnings. Each runtime job completes the source-bound checker with 211 main commands, twelve host programs and forty intended link controls, including all four new length programs and four old-seventeen controls. The separate nested CI case counts and artifact bytes were not retrieved; the detailed Rust/array/producer totals remain local results. Each Markdown job checks nine files with zero errors. Preceding push CI 9 and PR CI 10 pass only for seventeen-function source 4207509c862c6a42b79ccb06e0b01ef61e4727b2.

Matching eighteen-function API/manual updates are in progress in Docs PR #4. Signed Docs 928ff81a1d6dea09145f49fd4fbe07ab84525000, its nineteen API routes, complete 2,331-page manual and passing CI 833/834 remain evidence for the preceding seventeen-function interface.

Integration PR #12 still selects memory-only source 8270170c221260c444d923865461231e6ce622b2 for native links. This checkpoint does not establish guest execution of these new routines, full libc or a complete build of EriX within EriX.

Review checklist

  • Document pointer, count and link contracts; preserve earlier instructions.
  • Pass strict local crate, object, independent array and guarded C/Rust checks.
  • Keep component documents canonical and code below 1,000 physical lines.
  • Complete this signed source's component CI.
  • Complete matching manual/API refresh and local documentation validation.
  • Complete matching documentation CI.
  • Complete remaining libc, authority audit, workload and full guest-build acceptance.
## Summary and rationale Provide eighteen freestanding C byte and string operations through documented Rust declarations, partial C headers and one explicitly selected assembler companion. Add `strnlen`, which stops at the first NUL or the caller's full-width bound. Preserve all seventeen preceding function bodies. ## Tracking and scope - C runtime/libc design: #1; authority and quality audit: #2. - Signed source: `bdcbbea43550e8b99cd9a8221e4bc5a645637990` on `feature/posix-compat`. - Partial x86_64 SysV ELF object/archive and dependency-free `no_std` Rust interface. Startup, allocation, errno storage, remaining functions, POSIX adapters and full guest builds remain open. - The original Integration process helper remains pinned to `e2b1cf5995bcf6334839cda9a013e90fa97787d5`. ## Architecture, authority and failure behavior For a positive bound, `strnlen` requires initialized readable bytes through the first NUL or the complete bound, whichever comes first. It returns that NUL's index or the bound. No byte at the bound or after NUL is read, and the source cursor is not advanced after the last permitted byte. Count and return value retain the full 64-bit width. Only the namespaced raw zero-count interface expressly permits null; conventional C pointer rules remain applicable. The scalar leaf uses no stack scratch, allocation, syscall, errno access or shared state. It obtains no capabilities and retains no pointer. The returned count grants no memory access. Review removed a redundant loop comparison while preserving the pre-read and exhausted-bound checks; no measured speedup is claimed. Core/public/hidden policies share the same eighteen bodies. The query section is 178 bytes and preserves the original 152-byte prefix; the 234-byte memory, 136-byte writer and 344-byte span sections remain exact. Eight assembler source roles include zero-instruction alias files under every policy. Consumers must explicitly select the new revision and bytes. Missing or duplicate companions fail linkage. Receipts bind selected inputs without establishing repository provenance or the complete installed compiler closure. ## Validation evidence Matching Docs `7ccbe0bfa83ce5942878fb7cf8c57bb1abe75d00` is signed and pushed in [Docs PR #4](https://git.erikinkinen.fi/erix/docs/pulls/4). Its original-source references select ABI 2417b283 and eighteen-function libc bdcbbea, with 161 and twenty API routes respectively. All 44 documentation tests, both API checks and 55 Markdown files pass. The complete 2,339-page manual passes in 154.64 seconds with zero final warnings; all 425,255 word boxes fit and nine actual previews pass visual review. The first render was interrupted by an outer watchdog that could not observe the inner log; its failed statuses and clean cleanup are retained. The corrected outer budget preserves the inner hard/progress limits, and passing API/unit checks were reused. Matching Docs [push CI 837](https://git.erikinkinen.fi/erix/docs/actions/runs/837) and [PR CI 838](https://git.erikinkinen.fi/erix/docs/actions/runs/838) both pass for signed `7ccbe0bfa83ce5942878fb7cf8c57bb1abe75d00`, ending by 05:58:35 UTC on September 14. All four complete logs total 752,104 bytes and are correlated with the original workflow and build/publish scripts. Each manual job passes 44 tests and finishes at 2,339 pages with zero final-pass warnings; thirty first-pass and one second-pass convergence warnings resolve. Each Markdown job checks 55 files with zero errors. The logged CI PDF size is 4,105,617 bytes; CI artifact bytes and geometry were not independently inspected. Local layout and visual evidence remain separate. This adds no native metadata operation, companion migration or complete guest build result. Selected Rust 1.97.1 formatting, strict Clippy, warning-denied host/freestanding builds and private rustdoc pass. Each default/all-feature debug/release host invocation passes 33 Rust tests, for 132 executions. The feature set contains only empty `default`; those commands have identical effective features. Rust crate roots deny missing documentation. All 90 independent array cases, 23 producer controls and twelve mixed C/Rust programs pass. New witnesses cover all byte values, alignments, exact nonterminated bounds, read-only protected-page edges, early NUL and real callbacks with pointer/count arguments after six scalar register arguments. Large bounds over short terminated strings test argument width, not returned lengths above 2^32. Existing register, direction-flag and guarded-stack checks remain. Forty intentional link rejections cover missing, duplicate and older companions; the isolated old-seventeen control requires exactly the two new `strnlen` symbol names, preserving the earlier writer/span controls. All recorded object/archive outputs and original instruction witnesses correlate. Nine Markdown files, workflow shell syntax, canonical documents, source consistency, whitespace and code-size checks pass. The runtime matrix and dependent finishing checks complete without an unexpected failure or warning. A later ROADMAP-only result update receives the affected documentation/source checks without runtime replay. [Push CI 11](https://git.erikinkinen.fi/erix/lib-cstd/actions/runs/11) and [PR CI 12](https://git.erikinkinen.fi/erix/lib-cstd/actions/runs/12) both pass for signed bdcbbea, ending by 05:40:42 UTC on September 13. All four complete logs are retained (64,532 bytes), with no compiler or lint warnings. Each runtime job completes the source-bound checker with 211 main commands, twelve host programs and forty intended link controls, including all four new length programs and four old-seventeen controls. The separate nested CI case counts and artifact bytes were not retrieved; the detailed Rust/array/producer totals remain local results. Each Markdown job checks nine files with zero errors. Preceding [push CI 9](https://git.erikinkinen.fi/erix/lib-cstd/actions/runs/9) and [PR CI 10](https://git.erikinkinen.fi/erix/lib-cstd/actions/runs/10) pass only for seventeen-function source `4207509c862c6a42b79ccb06e0b01ef61e4727b2`. Matching eighteen-function API/manual updates are in progress in [Docs PR #4](https://git.erikinkinen.fi/erix/docs/pulls/4). Signed Docs `928ff81a1d6dea09145f49fd4fbe07ab84525000`, its nineteen API routes, complete 2,331-page manual and passing [CI 833](https://git.erikinkinen.fi/erix/docs/actions/runs/833)/[834](https://git.erikinkinen.fi/erix/docs/actions/runs/834) remain evidence for the preceding seventeen-function interface. [Integration PR #12](https://git.erikinkinen.fi/erix/integration/pulls/12) still selects memory-only source `8270170c221260c444d923865461231e6ce622b2` for native links. This checkpoint does not establish guest execution of these new routines, full libc or a complete build of EriX within EriX. ## Review checklist - [x] Document pointer, count and link contracts; preserve earlier instructions. - [x] Pass strict local crate, object, independent array and guarded C/Rust checks. - [x] Keep component documents canonical and code below 1,000 physical lines. - [x] Complete this signed source's component CI. - [x] Complete matching manual/API refresh and local documentation validation. - [ ] Complete matching documentation CI. - [ ] Complete remaining libc, authority audit, workload and full guest-build acceptance.
feat: Provide an explicit freestanding C memory companion
All checks were successful
CI / markdown (push) Successful in 11s
CI / memory (push) Successful in 41s
CI / markdown (pull_request) Successful in 3s
CI / memory (pull_request) Successful in 29s
8270170c22
Move the original EriX scalar memory instructions into one library-owned
assembler body with namespaced Rust declarations and an explicit partial C
header. Public and hidden aliases share that body without extra instructions;
callers retain range, lifetime and concurrency obligations.

Build the selected object and archive with explicit tools, original process
ownership, bounded commands and complete failure receipts. Cover byte ranges,
overlap, calling convention, guard boundaries, missing/duplicate companions,
producer failures and selected-source loading. Enforce missing documentation
and strict default/all-feature host and freestanding checks.

This is a partial memory runtime. Coordinated Integration consumers, generated
manual/API documentation, complete CI and native image validation remain open.
feat: Add read-only C byte and string queries
All checks were successful
CI / markdown (push) Successful in 12s
CI / markdown (pull_request) Successful in 12s
CI / memory (push) Successful in 1m24s
CI / memory (pull_request) Successful in 1m24s
2da6379aee
Provide original scalar strlen, strcmp, strncmp and memchr routines through the
same explicitly selected companion as the existing memory operations. Preserve
all memory instruction bytes while binding each new body and alias source to
the producer. Document caller-owned initialized ranges, termination, full-width
counts and returned-pointer access limits without allocation or service effects.

Add independent literal byte-array tests, guarded read-only boundary probes,
real C and Rust callbacks, register-state checks and missing or duplicate
companion rejection. Keep the component source and tool inputs explicit and
separate this leaf from guest toolchain and self-hosted build acceptance.

Validate formatting, strict Clippy, host and freestanding builds and rustdoc;
12 Rust cases in four configurations, 30 array cases, 19 producer controls,
four guarded C/Rust programs and 12 expected link rejections pass. Final
Markdown and workflow checks pass after correcting one overlong line. No
compiler warnings were observed; guest toolchain acceptance remains pending.
erikinkinen changed title from WIP: Provide an explicit freestanding C memory runtime to WIP: Provide explicit freestanding C memory and query routines 2026-09-13 01:08:49 +02:00
feat: Add first and last C character searches
All checks were successful
CI / markdown (push) Successful in 14s
CI / markdown (pull_request) Successful in 14s
CI / memory (push) Successful in 1m14s
CI / memory (pull_request) Successful in 1m15s
9853bcb8d4
Implement strchr and strrchr with one forward byte scan through each valid
terminated string. Document target char conversion, searchable NUL and raw
pointer access limits in Rustdoc and the partial C header. Preserve the original
memory and query instructions and use the existing explicit companion policies.

Validate literal and independent array cases, protected-page boundaries,
actual mixed C/Rust callbacks, external call relocations and calling state.
Formatting, strict Clippy, warning-denied host/freestanding builds and rustdoc
pass; 60 Rust test executions, 36 array cases, 19 producer controls and four
mixed host programs pass. Keep complete libc and guest build acceptance open.
feat: Implement bounded C string copies and concatenation
All checks were successful
CI / markdown (pull_request) Successful in 14s
CI / markdown (push) Successful in 14s
CI / memory (pull_request) Successful in 1m18s
CI / memory (push) Successful in 1m19s
d48bae1bb1
Add strcpy, strncpy, strcat and strncat through one original byte-loop
runtime section with versioned Rust entry points and opt-in public C aliases.
Document destination capacity, source validity, nonoverlap, zero counts,
padding and termination. Keep existing memory and query instructions intact;
the operations retain no pointers and require no allocation or authority.

Validation: strict formatting, Clippy, builds and rustdoc pass. Execute 92
Rust tests, 54 array cases, 21 producer controls, four guarded mixed C/Rust
programs and 16 expected link rejections. Preserve the corrected ctypes
fixture failure and Markdown wrapping failure. Affected documentation and
workflow checks pass. Component CI and coordinated manual refresh remain
pending; complete C runtime and guest self-hosting acceptance remain open.
erikinkinen changed title from WIP: Provide explicit freestanding C memory and query routines to WIP: Implement freestanding C memory and string primitives 2026-09-13 04:48:06 +02:00
feat: Add freestanding C string span and set queries
All checks were successful
CI / markdown (pull_request) Successful in 19s
CI / markdown (push) Successful in 19s
CI / memory (push) Successful in 1m25s
CI / memory (pull_request) Successful in 1m25s
4207509c86
Implement strspn, strcspn and strpbrk using caller-local 32-byte bitmaps.
Preserve byte-only input reads, NUL boundaries, read-only overlap and source
pointer permissions without shared state, heap allocation or service authority.
One selected companion retains all preceding memory and string instructions.

Validate formatting, strict Clippy, warning-denied host and freestanding
builds/rustdoc, 120 Rust test executions, 78 array tests and 23 producer
controls. Eight mixed C/Rust programs exercise guarded input and stack
boundaries, register preservation and deliberate checker faults; 28 expected
link rejections preserve missing and duplicate companion contracts.

The native Integration graph still selects its earlier memory-only source.
Matching generated documentation and guest/self-hosting acceptance remain
separate follow-ups; this partial runtime does not establish a full libc.
feat: Add bounded C string length
All checks were successful
CI / markdown (push) Successful in 15s
CI / markdown (pull_request) Successful in 15s
CI / memory (push) Successful in 1m29s
CI / memory (pull_request) Successful in 1m30s
bdcbbea435
Implement strnlen with full-width bounds and immediate stopping at NUL or
the caller count. Preserve every previous function body and avoid unused
endpoint arithmetic, shared state, allocation and runtime authority.

Document pointer obligations and the namespaced raw null-zero extension.
Check independent byte oracles, protected-page boundaries, mixed C/Rust
callbacks and exact missing-companion controls. Rust formatting, strict Clippy, host/freestanding builds and rustdoc pass.
All 132 Rust case executions, 90 array cases, 23 producer controls and 12
mixed programs pass; 40 intentional link failures reject as expected.
Documentation and source checks pass with no warnings. Matching manual
updates and component CI remain follow-up gates.
All checks were successful
CI / markdown (push) Successful in 15s
CI / markdown (pull_request) Successful in 15s
CI / memory (push) Successful in 1m29s
CI / memory (pull_request) Successful in 1m30s
This pull request is marked as a work in progress.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feature/posix-compat:feature/posix-compat
git switch feature/posix-compat

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff feature/posix-compat
git switch feature/posix-compat
git rebase main
git switch main
git merge --ff-only feature/posix-compat
git switch feature/posix-compat
git rebase main
git switch main
git merge --no-ff feature/posix-compat
git switch main
git merge --squash feature/posix-compat
git switch main
git merge --ff-only feature/posix-compat
git switch main
git merge feature/posix-compat
git push origin main
Sign in to join this conversation.
No description provided.