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