Files
libakerror/docs/status-codes.md
Andrew Kesterson 5695061130
Some checks failed
libakerror CI Build / cmake_build (push) Successful in 2m47s
libakerror CI Build / coverage (push) Successful in 2m48s
libakerror CI Build / thread_sanitizer (push) Failing after 2m49s
libakerror CI Build / mutation_test (push) Successful in 39m56s
Split the README reference material into docs/
The README was 794 lines: the summary, the design rationale, the whole macro
reference, the threading contract, the build internals and the exit-status
specification in one file. It is now 178 lines -- summary, installation,
quickstart, and an index -- and the reference material lives in docs/, one file
per topic: architecture, usage, status-codes, uncaught-errors, exit-status,
thread-safety, building.

The prose moved as written. Inbound references followed it: UPGRADING.md,
TODO.md, include/akerror.tmpl.h and tests/err_threads_handoff.c now name the
docs/ file that owns the text they cite, and AGENTS.md says where new
documentation goes so the README does not grow back.

Five factual errors fixed in the moved text:

- Both NULL-pointer examples inverted their test. FAIL_ZERO_* fails when the
  expression is zero, so `(somePointer == NULL)` failed on a *valid* pointer.
  They now read `(somePointer != NULL)`.
- AKERROR_NOIGNORE, four times including the #define, is AKERR_NOIGNORE.
- FINISH_NORExbTURN is FINISH_NORETURN.
- "functiions" is "functions".
- The architecture link pointed at include/akerror.h, which is generated and
  not in the tree; it points at include/akerror.tmpl.h.

The quickstart is new text. It compiles under -Wall -Wextra -Werror and was run
through all three of its paths: handled usage error exits 0, unhandled IO error
prints a trace and exits with the status, success exits 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 16:56:07 -04:00

2.2 KiB

Error codes

The library uses integer values to specify error codes inside of its context. These integer return codes are defined in akerror.h in the form of AKERR_xxxxx where xxxxx is the name of the error code in question. See akerror.h for a list of defined errors and their descriptions.

You can define additional error types as integer constants. Values 0 through 255 are reserved by libakerror (the host's errno values plus the AKERR_* codes); consumers allocate codes starting at AKERR_FIRST_CONSUMER_STATUS (256). Status names are stored sparsely, so any int is a legal status and no compile definition is needed to use large values. Note that no consumer status can be a process exit code — see Exit status.

Every library that may coexist in one process must reserve its range during initialization. akerr_reserve_status_range() and akerr_register_status_name() report failure the way everything else in this library does — they return akerr_ErrorContext *, and they are marked AKERR_NOIGNORE — so a collision is an exception you can CATCH, HANDLE, or PASS up out of your initialization:

#define MYLIB_OWNER "my-library"

akerr_ErrorContext AKERR_NOIGNORE *mylib_init(void)
{
    PREPARE_ERROR(errctx);

    /* Another component owning part of the range propagates to our caller. */
    PASS(errctx, akerr_reserve_status_range(256, 16, MYLIB_OWNER));

    /* Then name each code, quoting the owner you reserved with. */
    PASS(errctx, akerr_register_status_name(MYLIB_OWNER, 256,
                                            "Some Error Code Description"));
    SUCCEED_RETURN(errctx);
}

Reservations are process-local, fixed-capacity, and idempotent when the same owner repeats the exact same range. They preserve compile-time integer constants so HANDLE still works, since case labels require them.

Naming a status outside your reservation raises AKERR_STATUS_NAME_FOREIGN, and naming one nobody reserved raises AKERR_STATUS_NAME_UNRESERVED; a colliding reservation raises AKERR_STATUS_RANGE_OVERLAP, with a message naming the real owner. See UPGRADING.md for the full list of statuses these two functions raise, the capacity limits and how to raise them, and thread-safety rules.