Skip to content
📖 Auto vs Modern CBook contents

Chapter 19: Variations in Control Flow ​

Level 3 -- Experience

Non-local jumps, signals, and structured error handling -- understanding C's control flow escape hatches and how Auto replaces them with safer patterns.

Programs don't always follow a straight-line path. Functions return early, loops break out, errors propagate through call stacks. C provides several mechanisms for non-standard control flow: goto, setjmp/longjmp, and signal handlers. These are powerful but dangerous. Auto replaces most of them with structured alternatives.


19.1 A Detailed Example ​

Consider a parser that must handle errors at multiple levels:

c
// C Deep Dive: error handling with goto
#include <stdio.h>
#include <stdlib.h>

int parse_input(const char *input) {
    if (!input) goto error_null;
    if (*input == '\0') goto error_empty;

    int value = atoi(input);
    if (value <= 0) goto error_negative;

    printf("Parsed: %d\n", value);
    return value;

error_null:
    fprintf(stderr, "Error: null input\n");
    return -1;
error_empty:
    fprintf(stderr, "Error: empty input\n");
    return -2;
error_negative:
    fprintf(stderr, "Error: non-positive value\n");
    return -3;
}

C programmers use goto for centralized error cleanup. It is one of the few accepted uses of goto in C. The pattern is: jump to a label that releases resources and reports the error.

Auto's approach. Auto uses Result types for error propagation:

auto
// Auto: Result type for structured error handling
type ParseResult {
    value int
    ok bool
    error str
}

fn ParseResult.ok(val int) ParseResult {
    ParseResult(val, true, "")
}

fn ParseResult.err(msg str) ParseResult {
    ParseResult(0, false, msg)
}

fn parse_input(input str) ParseResult {
    if input == "" {
        return ParseResult.err("empty input")
    }
    let value int = int(input)
    if value <= 0 {
        return ParseResult.err("non-positive value")
    }
    ParseResult.ok(value)
}

Released under the MIT License.