kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

cflags.h (3059B)


      1 #ifndef KIT_DRIVER_CFLAGS_H
      2 #define KIT_DRIVER_CFLAGS_H
      3 
      4 #include <kit/compile.h>
      5 
      6 #include "driver.h"
      7 
      8 /* Shared parsing of the C-preprocessor flag family used by both `cc` and
      9  * `run`: -I, -isystem, -D, -U. Owns a back-store sized to the worst-case
     10  * argv slot count so callers can hold borrowed pointers into argv without
     11  * a second growth step.
     12  *
     13  * Usage:
     14  *   DriverCflags cf = {0};
     15  *   if (driver_cflags_init(&cf, env, argc) != 0) return 1;
     16  *   for (i = 1; i < argc; ++i) {
     17  *       int r = driver_cflags_try_consume(&cf, env, TOOL, argc, argv, &i);
     18  *       if (r < 0) { driver_cflags_fini(&cf, env); return 1; }
     19  *       if (r) continue;
     20  *       ... handle other flags / positionals ...
     21  *   }
     22  *   driver_cflags_fill_pp(&cf, &pp_out);
     23  *   ... use pp_out ...
     24  *   driver_cflags_fini(&cf, env);
     25  *
     26  * The (name, body) pairs from `-Dname=body` are stored in heap-allocated
     27  * NUL-terminated names; the body slices argv directly. Standalone `-Dname`
     28  * entries reuse argv for both name and body=NULL. */
     29 typedef struct DriverCflags {
     30   const char** include_dirs;
     31   uint32_t ninclude_dirs;
     32   const char** system_include_dirs;
     33   uint32_t nsystem_include_dirs;
     34   KitDefine* defines;
     35   uint32_t ndefines;
     36   KitSlice* undefines;
     37   uint32_t nundefines;
     38 
     39   /* Internal storage for the names of `-Dname=body` defines we had to
     40    * split (entries are NULL when the body was unspecified — argv already
     41    * provides a NUL-terminated name). Indexed in parallel with defines[];
     42    * sizes are needed to free through the heap. */
     43   char** _owned_define_names;
     44   size_t* _owned_define_name_sizes;
     45   size_t _cap; /* element count of every parallel array */
     46 } DriverCflags;
     47 
     48 /* Allocate the back-store. `argc_bound` is the upper limit on the number of
     49  * each kind of flag the caller might collect (typically the program's
     50  * argc). Returns 0 on success, 1 on allocation failure (already reported). */
     51 int driver_cflags_init(DriverCflags*, DriverEnv*, int argc_bound);
     52 
     53 /* Release every allocation held by *cf. Safe to call even after a failed
     54  * init: unused slots are NULL/0 and free becomes a no-op. */
     55 void driver_cflags_fini(DriverCflags*, DriverEnv*);
     56 
     57 /* Try to consume one cflag at argv[*i]. Recognized: -I dir, -Idir, -isystem
     58  * dir, -D name[=body], -Dname[=body], -U name, -Uname.
     59  *
     60  * Returns:
     61  *   1  flag matched and was consumed (advances *i past the flag and any
     62  *      separate value argument).
     63  *   0  the arg at argv[*i] is not a cflag we handle.
     64  *  -1  the arg matched a cflag prefix but its value/argument is missing or
     65  *      allocation failed; the error has already been reported via
     66  *      driver_errf(tool, ...). */
     67 int driver_cflags_try_consume(DriverCflags*, DriverEnv*, const char* tool,
     68                               int argc, char** argv, int* i);
     69 
     70 /* Populate a KitPreprocessOptions from the accumulated flags. The
     71  * struct borrows the cf-owned arrays; the caller must keep cf alive
     72  * across any libkit call that consumes pp_out. */
     73 void driver_cflags_fill_pp(const DriverCflags*, KitPreprocessOptions* pp_out);
     74 
     75 #endif