Wrap the strings, streams and collections the wishlist asked for
TODO.md section 3.1's high-priority list and section 3.6's data
structures. This is the surface akbasic went without: it makes 10 calls
into this library and 116 to raw libc, and 69 of those 116 are strlen,
strcmp, strncpy and strstr.
Three new translation units, because src/stdlib.c covering four times
what it did would stop being readable:
src/string.c lengths, bounded copy and concatenation, duplication,
comparison including the case-insensitive forms,
searching, the reentrant tokenisers, and a status
message that knows this library's own statuses as
well as errno's.
src/stream.c positioning, flushing and buffering, character and
line I/O, stream state, freopen/fdopen/tmpfile,
formatted input, and the file operations.
src/collections.c the list functions that were missing, a head/tail
container so append is O(1), a binary search tree,
FNV-1a, a fixed-capacity hash map and a growable
string buffer.
Two conventions run through all of it. The copying functions take the
destination size even where the libc function they are named for does
not, because strcpy(3) cannot be called safely without it, and
truncation is an error that writes nothing rather than a plausible
prefix -- this is the idiom akbasic writes out by hand at ten sites.
The searching functions treat "not found" as a successful answer of
NULL, because absent is an answer and raising on it would make every
caller handle a non-error.
The hash map is akbasic's src/symtab.c generalised: open-addressed with
linear probing over a caller-supplied slot array, keys copied into fixed
slots so the map owns them, tombstones on delete so a removal cannot cut
a probe chain, and a refusal rather than a resize when full.
Tests: 16 binaries, green under the normal and sanitizer builds. The
scanf wrappers take the number of conversions the caller expects, since
comparing scanf(3)'s return against that by hand is the check everyone
eventually forgets.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
14
src/stdlib.c
14
src/stdlib.c
@@ -8,19 +8,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* errno as an akerror status, with a fallback for when it is not one.
|
||||
*
|
||||
* A libc call is allowed to fail without touching errno -- malloc(0) may return
|
||||
* NULL and leave it alone -- and errno may equally be a leftover from some
|
||||
* earlier, unrelated, *successful* call. Reporting it raw produced a FAIL whose
|
||||
* status was 0, which every downstream DETECT and CATCH reads as success while
|
||||
* the context still holds a pool slot: an error that is invisible and leaks at
|
||||
* the same time. Every errno-sourced status in this file goes through here, and
|
||||
* every wrapped call clears errno first so the value read back is its own.
|
||||
* TODO.md 2.2.1.
|
||||
*/
|
||||
#define AKSL_ERRNO_OR(__fallback) (errno != 0 ? errno : (__fallback))
|
||||
#include "aksl_internal.h"
|
||||
|
||||
/*
|
||||
* Version of the library itself. These read the AKSL_VERSION_* macros as they
|
||||
|
||||
Reference in New Issue
Block a user