/* * 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 := props* * * The eight kinds mirror GNU Autoconf's "Existing Tests" (manual ยง5) and * pkg-config's PKG_CHECK_MODULES: * * header arg = header name -> #include probe * e.g. header "pthread.h" * function arg = function name -> link probe for the symbol * e.g. function "strdup" * library arg = library name -> -l 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() probe * e.g. sizeof "long" * program arg = program name -> command -v probe * e.g. program "pkg-config" * compiler_flag arg = flag -> compile probe with added * e.g. compiler_flag "-fsanitize=address" * pkg_config arg = package name -> pkg-config --cflags --libs * 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 "": one of >= <= = > <, * 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 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 */