## c return status ## type ``` typedef struct { int id; char* group; } status_t; ``` `id == 0` denotes success. `id != 0` denotes failure. a status is identified by `(group, id)`. the canonical success value is: ``` { status_id_success, status_group_undefined } ``` ## applicability only functions that can fail return `status_t`. functions that cannot fail do not return `status_t`. this is a semantic partition, not a stylistic choice. ## local carrier a fallible function declares: ``` status_declare; ``` this establishes a success-initialized local status. ## control ### assignment ``` status_set(group_id, status_id); ``` ### transfer ``` status_goto; status_set_goto(group_id, status_id); ``` control transfers to: ``` exit: ``` ### return ``` status_return; status_i_return; ``` ## propagation ### status-returning callee ``` status_require(callee(...)); ``` semantics: * assign result to `status` * if `status.id != 0`, transfer to `exit` ### integer-returning callee ``` status_i_require(callee(...)); ``` semantics: * assign result to `status.id` * if `status.id != 0`, transfer to `exit` group assignment is the caller's responsibility. ### direct return ``` status_require_return(callee(...)); ``` ## cleanup a function may define a single convergence point: ``` exit: ``` both normal and failure paths may reach it. ### resource state each owned resource has a neutral value representing "not owned". the resource variable itself encodes ownership state. no auxiliary tracking variables are introduced if the resource variable suffices. ### preparation pattern for each resource: * initialize variable to its neutral value before acquisition * acquisition moves it to owned state * no other state is relevant ### cleanup rule at `exit:`: * release each resource whose variable denotes ownership * do not release resources in neutral state * do not release any resource more than once cleanup is expressed solely in terms of resource variables. ## invariants * `status.id == 0` implies success * `status.id != 0` implies failure * `(group, id)` identifies the failure * propagation preserves `(group, id)` unless reassigned * cleanup correctness depends only on resource variables, not on auxiliary flags ## minimal correctness criterion the convention is correct if and only if: * all fallible functions return `status_t` * all failure paths transfer to a single `exit:` or return immediately * all owned resources are released exactly once at `exit:` * resource ownership is encoded only in the resource variables themselves