Files
stupidtools/src/detect/check_registry.h
T

141 lines
6.5 KiB
C

/*
* check_registry.h - declarative feature-check kinds for stupidtools
* (todo 10).
*
* A `feature "name" { check* }` block's children are CHECK nodes. Each
* check node's NAME is one of eight fixed keywords - the check KINDS -
* and its FIRST (and only) positional argument is the TARGET the check
* is about:
*
* check := <name> <arg> props*
*
* The eight kinds mirror GNU Autoconf's "Existing Tests" (manual §5) and
* pkg-config's PKG_CHECK_MODULES:
*
* header arg = header name -> #include <arg> probe
* e.g. header "pthread.h"
* function arg = function name -> link probe for the symbol
* e.g. function "strdup"
* library arg = library name -> -l<arg> link probe
* e.g. library "pthread"
* type arg = type name -> compile probe for the type
* e.g. type "size_t"
* sizeof arg = type name -> sizeof(<arg>) probe
* e.g. sizeof "long"
* program arg = program name -> command -v <arg> probe
* e.g. program "pkg-config"
* compiler_flag arg = flag -> compile probe with <arg> added
* e.g. compiler_flag "-fsanitize=address"
* pkg_config arg = package name -> pkg-config --cflags --libs <arg>
* e.g. pkg_config "openssl"
*
* WHAT THIS TODO OWNS
* -------------------
* Only the DECLARATIVE SHAPE: the kind enumeration, the kind<->keyword
* mapping, and per-kind argument/property shape as DATA (the table
* below). It deliberately does NOT implement probe generation (todo 11)
* or probe execution/caching (todo 12). src/kdl/schema.c consumes the
* mapping + table to enforce the DSL (see its todo-10 HOOK); todos 11
* and 16 consume the same table to generate probes and substitute
* results - THIS HEADER IS THE CONTRACT for them.
*
* OPTIONAL `version` CONSTRAINT (library and pkg_config)
* ------------------------------------------------------
* `library` and `pkg_config` may carry an optional version constraint,
* spelled EXACTLY like the project node's version (pinned by todo 9):
* the literal keyword `version` followed by a constraint string, as two
* further positional arguments:
*
* library "curl" version ">=7.0"
* pkg_config "openssl" version ">=1.1"
*
* The constraint is "<op><version>": <op> one of >= <= = > <, <version>
* a dotted numeric version. Todo 10 pins only the SHAPE (the keyword +
* a non-empty unannotated string); the OPERATOR SEMANTICS are
* interpreted by todo 11 (probe generation) and todo 16 (result
* substitution). The spelling is an argument pair, not a KDL property,
* because this parser classifies `version "..."` as two positional
* arguments - the same reason the project node spells it that way. The
* property form `version="..."` is NOT part of the DSL and is rejected
* (see PROPERTIES below).
*
* PROPERTIES
* ----------
* No check kind accepts properties in this todo (the grammar's `props*`
* is always empty for now); the schema validator rejects them with a
* spanned error. The shape table carries no props column for the same
* reason - todos 11/16 derive everything from the argument counts.
*
* ERRORS
* ------
* st_check_kind_from_node() reports unknown/empty check names as owned
* ST_ERR_KDL_SCHEMA errors whose span is heap-allocated IN THE SAME
* BLOCK as the error (the parser.c pattern), so err->span stays valid
* until st_error_free(err). The span points at the node's name token.
*
* Copyright (c) 2026 huntedbytheirs
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef ST_DETECT_CHECK_REGISTRY_H
#define ST_DETECT_CHECK_REGISTRY_H
#include <stddef.h>
struct st_error;
struct st_kdl_node;
/* The eight declarative check kinds, in canonical order. */
enum st_check_kind {
ST_CHECK_HEADER = 0, /* header "pthread.h" */
ST_CHECK_FUNCTION, /* function "strdup" */
ST_CHECK_LIBRARY, /* library "pthread" -> -lpthread */
ST_CHECK_TYPE, /* type "size_t" */
ST_CHECK_SIZEOF, /* sizeof "long" */
ST_CHECK_PROGRAM, /* program "pkg-config" -> command -v */
ST_CHECK_COMPILER_FLAG, /* compiler_flag "-fsanitize=address" */
ST_CHECK_PKG_CONFIG, /* pkg_config "openssl" */
ST_CHECK_KIND_COUNT, /* sentinel: number of real kinds above */
};
/* The DSL shape of one check kind, as DATA (consumed by the schema
* validator and by todos 11/16). */
struct st_check_shape {
enum st_check_kind kind; /* the kind this row describes */
const char *name; /* DSL keyword spelling, e.g. "header" */
const char *arg_meaning; /* what the required argument names, e.g.
"header name" */
size_t required_args; /* positional args the node MUST carry */
size_t optional_args; /* further positional args tolerated; 2
for library/pkg_config = the literal
`version` keyword followed by the
version constraint string (see the
header comment); 0 elsewhere */
};
/* The registry table: one row per kind, indexed by the ST_CHECK_*
* values (st_check_shapes[k].kind == k). */
extern const struct st_check_shape st_check_shapes[ST_CHECK_KIND_COUNT];
/* Map a feature's check child node to its kind by the node NAME. The
* name may be any KDL string form (bare identifier or quoted). Returns
* the kind and leaves *err untouched on success. On failure returns
* ST_CHECK_KIND_COUNT and sets *err to an owned ST_ERR_KDL_SCHEMA error
* whose span points at the node's name: an unknown keyword, an empty
* name, or (defensively) a NULL node. */
enum st_check_kind st_check_kind_from_node(const struct st_kdl_node *node,
struct st_error **err);
/* Stable DSL keyword for a kind (e.g. "header"). Kinds outside the
* table yield "?" rather than indexing out of range. */
const char *st_check_kind_name(enum st_check_kind kind);
/* The shape-table row for a kind, or NULL when `kind` is not a real
* kind. */
const struct st_check_shape *st_check_kind_shape(enum st_check_kind kind);
/* Number of real kinds (ST_CHECK_KIND_COUNT). */
size_t st_check_kind_count(void);
#endif /* ST_DETECT_CHECK_REGISTRY_H */