AxlSubcommand — Multi-command CLI dispatch

Helper for UEFI applications that expose multiple distinct operations under a common executable (do bios, do sysid, do crb …). Pairs with AxlConfig — Configuration — each subcommand uses its own AxlConfig descriptor table for flag parsing.

See AxlSys — System Utilities for an overview of all utility modules.

Header: <axl/axl-subcommand.h>

Single-purpose tools (e.g. mkrd) skip this layer and use axl_config_* directly. Multi-command tools (e.g. do.efi) declare an AxlSubcommand table and call axl_subcommand_dispatch from main.

API Reference

Typedefs

typedef int (*AxlSubcommandFn)(int argc, char **argv)

axl-subcommand.h:

Subcommand-style CLI dispatch for multi-command UEFI apps. Pairs with axl-config (each subcommand can use its own AxlConfig descriptor table for flag parsing) — mkrd is the canonical “single-purpose tool” shape, do.efi and friends are the canonical “multi-command tool” shape.

Usage:

static int do_bios(int argc, char **argv) { // argv[0] is “bios”; flags via axl_config_* return 0; } static int do_sysid(int argc, char **argv) { // argv[0] is “sysid” return 0; }

static const AxlSubcommand kCommands[] = { { “bios”, do_bios, “[test|pci|irq|slot|emb]”, “do bios test — run BIOS POST self-test\n” “do bios pci — dump PCI bus info\n” }, { “sysid”, do_sysid, “[hexValue]”, “do sysid — print system ID\n” “do sysid <hex> — set system ID\n” }, };

int main(int argc, char **argv) { return axl_subcommand_dispatch(kCommands, sizeof(kCommands) / sizeof(kCommands[0]), argc, argv, “do”); } Subcommand implementation function signature.

Receives (argc, argv) where argv[0] is the subcommand name (the dispatcher rewrites it from the parent’s argv so subcommand implementations don’t need to know about the parent’s name). Use AxlConfig or hand-written parsing on the remaining args.

Functions

int axl_subcommand_dispatch(const AxlSubcommand *table, size_t count, int argc, char **argv, const char *prog_name)

Dispatch argv[1] to the matching subcommand, or print help.

Behavior:

  • argc < 2, or argv[1] is “help” / “-h” / “–help” with no further args → prints the formatted help table and returns 0.

  • argv[1] is “help <cmd>” → prints cmd’s usage field (or summary if usage is NULL) and returns 0.

  • argv[1] matches a table entry → invokes its fn with (argc - 1, argv + 1) so the subcommand sees its own name as argv[0]. Returns the function’s return value.

  • argv[1] doesn’t match anything → prints “<prog>: unknown command

    ’foo’” plus a “did you mean ‘bar’?” suggestion if a close match exists, and returns -1.

The table is 100% caller-owned. No allocation; no internal state.

Parameters:
  • table – array of AxlSubcommand

  • count – number of entries in table

  • argc – forwarded from main()

  • argv – forwarded from main()

  • prog_name – used in help / error output. NULL → use the basename of argv[0].

Returns:

whatever the subcommand returned, 0 for help/empty, or -1 if the command wasn’t found.

void axl_subcommand_print_help(const AxlSubcommand *table, size_t count, const char *prog_name)

Print only the formatted help table.

Useful when the caller wants to show help in response to an invalid argument outside the dispatch path. Output format:

Usage: <prog> <command> [args…]

Commands: bios [test|pci|irq|slot|emb] sysid [hexValue]

Run ‘<prog> help <command>’ for detailed usage.

void axl_subcommand_print_command_help(const AxlSubcommand *entry, const char *prog_name)

Print a single subcommand’s detailed usage.

Used by <prog> help <cmd>. Prints entry->usage, falling back to entry->summary if entry->usage is NULL. Pass NULL entry to print the global help (same as axl_subcommand_print_help).

struct AxlSubcommand
#include <axl-subcommand.h>

One entry in a subcommand table. Define a static array of these (or allocate dynamically — the dispatcher doesn’t care) and pass it to axl_subcommand_dispatch.

Public Members

const char *name

e.g. “bios”, “sysid”, “crb”

AxlSubcommandFn fn

Implementation function.

const char *summary

One-line, shown in <prog> help

const char *usage

Multiline, shown in <prog> help <cmd> (NULL = use summary)