cflags.c (5526B)
1 #include "cflags.h" 2 3 #include <stddef.h> 4 #include <stdint.h> 5 6 int driver_cflags_init(DriverCflags* cf, DriverEnv* env, int argc_bound) { 7 size_t bound = argc_bound > 0 ? (size_t)argc_bound + 4u : 4u; 8 cf->_cap = bound; 9 cf->include_dirs = 10 driver_alloc_zeroed(env, bound * sizeof(*cf->include_dirs)); 11 cf->system_include_dirs = 12 driver_alloc_zeroed(env, bound * sizeof(*cf->system_include_dirs)); 13 cf->defines = driver_alloc_zeroed(env, bound * sizeof(*cf->defines)); 14 cf->_owned_define_names = 15 driver_alloc_zeroed(env, bound * sizeof(*cf->_owned_define_names)); 16 cf->_owned_define_name_sizes = 17 driver_alloc_zeroed(env, bound * sizeof(*cf->_owned_define_name_sizes)); 18 cf->undefines = driver_alloc_zeroed(env, bound * sizeof(*cf->undefines)); 19 if (!cf->include_dirs || !cf->system_include_dirs || !cf->defines || 20 !cf->_owned_define_names || !cf->_owned_define_name_sizes || 21 !cf->undefines) { 22 return 1; 23 } 24 return 0; 25 } 26 27 void driver_cflags_fini(DriverCflags* cf, DriverEnv* env) { 28 size_t cap = cf->_cap; 29 uint32_t i; 30 if (cf->_owned_define_names) { 31 for (i = 0; i < cf->ndefines; ++i) { 32 if (cf->_owned_define_names[i]) { 33 driver_free(env, cf->_owned_define_names[i], 34 cf->_owned_define_name_sizes[i]); 35 } 36 } 37 } 38 driver_free(env, cf->include_dirs, cap * sizeof(*cf->include_dirs)); 39 driver_free(env, cf->system_include_dirs, 40 cap * sizeof(*cf->system_include_dirs)); 41 driver_free(env, cf->defines, cap * sizeof(*cf->defines)); 42 driver_free(env, cf->_owned_define_names, 43 cap * sizeof(*cf->_owned_define_names)); 44 driver_free(env, cf->_owned_define_name_sizes, 45 cap * sizeof(*cf->_owned_define_name_sizes)); 46 driver_free(env, cf->undefines, cap * sizeof(*cf->undefines)); 47 cf->_cap = 0; 48 } 49 50 /* Split `name[=body]` into a heap-owned NUL-terminated name and a body that 51 * aliases the original argv tail. Returns 0 on success, 1 on alloc failure. */ 52 static int cflags_record_define(DriverCflags* cf, DriverEnv* env, 53 const char* arg) { 54 const char* eq = driver_strchr(arg, '='); 55 KitDefine* d = &cf->defines[cf->ndefines]; 56 if (eq) { 57 size_t n = (size_t)(eq - arg); 58 size_t bytes = n + 1; 59 char* name = driver_alloc(env, bytes); 60 if (!name) return 1; 61 driver_memcpy(name, arg, n); 62 name[n] = '\0'; 63 cf->_owned_define_names[cf->ndefines] = name; 64 cf->_owned_define_name_sizes[cf->ndefines] = bytes; 65 d->name = (KitSlice){.s = name, .len = n}; 66 d->body = kit_slice_cstr(eq + 1); 67 } else { 68 d->name = kit_slice_cstr(arg); 69 d->body = KIT_SLICE_NULL; 70 } 71 cf->ndefines++; 72 return 0; 73 } 74 75 /* Pull the value for a flag that accepts either `-Xvalue` or `-X value`. 76 * `prefix_len` is the byte length of `-X` itself (e.g. 2 for `-I`/`-D`/`-U`, 77 * larger for `-isystem`). On the attached form (`-Xvalue`) returns argv[*i] 78 * + prefix_len without advancing. On the separate form, advances *i to the 79 * value slot and returns argv[*i]; if no value follows, reports a diagnostic 80 * and returns NULL. */ 81 static const char* cflags_pull_value(const char* tool, int argc, char** argv, 82 int* i, size_t prefix_len, 83 const char* flag_label) { 84 const char* a = argv[*i]; 85 if (a[prefix_len]) return a + prefix_len; 86 if (++(*i) >= argc) { 87 driver_errf(tool, "%.*s requires an argument", 88 KIT_SLICE_ARG(kit_slice_cstr(flag_label))); 89 return NULL; 90 } 91 return argv[*i]; 92 } 93 94 int driver_cflags_try_consume(DriverCflags* cf, DriverEnv* env, 95 const char* tool, int argc, char** argv, int* i) { 96 const char* a = argv[*i]; 97 98 if (driver_strneq(a, "-I", 2)) { 99 const char* dir = cflags_pull_value(tool, argc, argv, i, 2, "-I"); 100 if (!dir) return -1; 101 cf->include_dirs[cf->ninclude_dirs++] = dir; 102 return 1; 103 } 104 105 if (driver_streq(a, "-isystem")) { 106 if (++(*i) >= argc) { 107 driver_errf(tool, "-isystem requires an argument"); 108 return -1; 109 } 110 cf->system_include_dirs[cf->nsystem_include_dirs++] = argv[*i]; 111 return 1; 112 } 113 114 if (driver_strneq(a, "-iquote", 7)) { 115 const char* dir = cflags_pull_value(tool, argc, argv, i, 7, "-iquote"); 116 if (!dir) return -1; 117 cf->include_dirs[cf->ninclude_dirs++] = dir; 118 return 1; 119 } 120 121 if (driver_strneq(a, "-idirafter", 10)) { 122 const char* dir = cflags_pull_value(tool, argc, argv, i, 10, "-idirafter"); 123 if (!dir) return -1; 124 cf->system_include_dirs[cf->nsystem_include_dirs++] = dir; 125 return 1; 126 } 127 128 if (driver_strneq(a, "-D", 2)) { 129 const char* arg = cflags_pull_value(tool, argc, argv, i, 2, "-D"); 130 if (!arg) return -1; 131 if (cflags_record_define(cf, env, arg) != 0) { 132 driver_errf(tool, "out of memory"); 133 return -1; 134 } 135 return 1; 136 } 137 138 if (driver_strneq(a, "-U", 2)) { 139 const char* arg = cflags_pull_value(tool, argc, argv, i, 2, "-U"); 140 if (!arg) return -1; 141 cf->undefines[cf->nundefines++] = kit_slice_cstr(arg); 142 return 1; 143 } 144 145 return 0; 146 } 147 148 void driver_cflags_fill_pp(const DriverCflags* cf, KitPreprocessOptions* pp) { 149 KitPreprocessOptions z = {0}; 150 *pp = z; 151 pp->include_dirs = cf->include_dirs; 152 pp->ninclude_dirs = cf->ninclude_dirs; 153 pp->system_include_dirs = cf->system_include_dirs; 154 pp->nsystem_include_dirs = cf->nsystem_include_dirs; 155 pp->defines = cf->defines; 156 pp->ndefines = cf->ndefines; 157 pp->undefines = cf->undefines; 158 pp->nundefines = cf->nundefines; 159 }