main.c (20243B)
1 #include <kit/config.h> 2 3 #include "driver.h" 4 5 /* Multi-call dispatch. Looks at argv[0]'s basename for a tool name; if argv[0] 6 * is the bare "kit" binary, falls back to argv[1]. 7 * 8 * Tool availability is centralized here. The Makefile uses the same 9 * KIT_TOOL_*_ENABLED flags to drop driver/<tool>.c objects, so disabled 10 * tools do not need #if checks scattered through each tool implementation. 11 */ 12 13 typedef int (*DriverToolMain)(int argc, char** argv); 14 typedef int (*DriverToolMainEx)(int argc, char** argv, 15 const KitDriverExtension*); 16 typedef void (*DriverToolHelp)(void); 17 18 typedef enum DriverHelpGroup { 19 DRIVER_HELP_BUILD, 20 DRIVER_HELP_BINARY, 21 DRIVER_HELP_EXECUTION, 22 DRIVER_HELP_DISTRIBUTION, 23 DRIVER_HELP_DATA, 24 DRIVER_HELP_KIT, 25 DRIVER_HELP_GROUP_COUNT, 26 } DriverHelpGroup; 27 28 typedef struct DriverToolDesc { 29 const char* name; 30 DriverToolMain main; 31 DriverToolMainEx main_ex; 32 DriverToolHelp help; 33 const char* summary; 34 /* Task-oriented presentation category for the top-level help inventory. */ 35 DriverHelpGroup help_group; 36 /* DriverToolGroup bits; 0 => not in the default install set */ 37 unsigned groups; 38 } DriverToolDesc; 39 40 static int driver_version_command(int argc, char** argv); 41 static void driver_help_version_command(void); 42 43 static const DriverToolDesc driver_tools[] = { 44 #if KIT_TOOL_CC_ENABLED 45 {"cc", driver_cc, NULL, driver_help_cc, 46 "Compile (and link) C sources, with cpp / dep-emit / ELF -shared modes", 47 DRIVER_HELP_BUILD, DRIVER_GROUP_TOOLCHAIN}, 48 #endif 49 #if KIT_TOOL_CHECK_ENABLED 50 {"check", driver_check, NULL, driver_help_check, 51 "Run C frontend checks without emitting code", DRIVER_HELP_BUILD, 52 DRIVER_GROUP_OTHER}, 53 #endif 54 #if KIT_TOOL_BUILD_EXE_ENABLED 55 {"build-exe", driver_build_exe, driver_build_exe_ex, driver_help_build_exe, 56 "Compile a polyglot source set and link an executable (in memory)", 57 DRIVER_HELP_BUILD, DRIVER_GROUP_TOOLCHAIN}, 58 #endif 59 #if KIT_TOOL_BUILD_LIB_ENABLED 60 {"build-lib", driver_build_lib, driver_build_lib_ex, driver_help_build_lib, 61 "Compile sources into a static .a or ELF shared library (in memory)", 62 DRIVER_HELP_BUILD, DRIVER_GROUP_TOOLCHAIN}, 63 #endif 64 #if KIT_TOOL_BUILD_OBJ_ENABLED 65 {"build-obj", driver_build_obj, driver_build_obj_ex, driver_help_build_obj, 66 "Compile sources to an object / asm / C / IR, or check (replaces compile)", 67 DRIVER_HELP_BUILD, DRIVER_GROUP_TOOLCHAIN}, 68 #endif 69 #if KIT_TOOL_BUILD_ENABLED 70 {"build", driver_build, NULL, driver_help_build, 71 "Resolve a target with the content-addressed build coordinator", 72 DRIVER_HELP_BUILD, DRIVER_GROUP_OTHER}, 73 #endif 74 #if KIT_TOOL_MAKE_ENABLED 75 {"make", driver_make, NULL, driver_help_make, 76 "Bring targets up to date from a makefile (POSIX make)", 77 DRIVER_HELP_BUILD, DRIVER_GROUP_OTHER}, 78 #endif 79 #if KIT_TOOL_INSTALL_ENABLED 80 {"install", driver_install, NULL, driver_help_install, 81 "Symlink the kit tools into a dir for drop-in toolchain use", 82 DRIVER_HELP_KIT, DRIVER_GROUP_OTHER}, 83 #endif 84 #if KIT_TOOL_CPP_ENABLED 85 {"cpp", driver_cpp, NULL, driver_help_cpp, 86 "Standalone C preprocessor (alias for `cc -E` minus link scaffold)", 87 DRIVER_HELP_BUILD, DRIVER_GROUP_TOOLCHAIN}, 88 #endif 89 #if KIT_TOOL_AS_ENABLED 90 {"as", driver_as, NULL, driver_help_as, 91 "Assemble a GAS-subset text source into a relocatable object", 92 DRIVER_HELP_BUILD, DRIVER_GROUP_TOOLCHAIN}, 93 #endif 94 #if KIT_TOOL_LD_ENABLED 95 {"ld", driver_ld, NULL, driver_help_ld, 96 "Link objects/archives into an executable or ELF shared library", 97 DRIVER_HELP_BUILD, DRIVER_GROUP_TOOLCHAIN}, 98 #endif 99 #if KIT_TOOL_AR_ENABLED 100 {"ar", driver_ar, NULL, driver_help_ar, 101 "Create / modify / list / extract POSIX `ar` archives", DRIVER_HELP_BINARY, 102 DRIVER_GROUP_TOOLCHAIN}, 103 #endif 104 #if KIT_TOOL_CPIO_ENABLED 105 {"cpio", driver_cpio, NULL, driver_help_cpio, 106 "Create / list / extract SVR4 newc cpio (initramfs) archives", 107 DRIVER_HELP_BINARY, DRIVER_GROUP_TOOLCHAIN}, 108 #endif 109 #if KIT_TOOL_RANLIB_ENABLED 110 {"ranlib", driver_ranlib, NULL, driver_help_ranlib, 111 "Refresh the symbol index of an `ar` archive", DRIVER_HELP_BINARY, 112 DRIVER_GROUP_TOOLCHAIN}, 113 #endif 114 #if KIT_TOOL_STRIP_ENABLED 115 {"strip", driver_strip, NULL, driver_help_strip, 116 "Drop debug sections and/or symbols from a .o or .a", DRIVER_HELP_BINARY, 117 DRIVER_GROUP_TOOLCHAIN}, 118 #endif 119 #if KIT_TOOL_OBJCOPY_ENABLED 120 {"objcopy", driver_objcopy, NULL, driver_help_objcopy, 121 "Copy and transform an object file (rename / remove / format)", 122 DRIVER_HELP_BINARY, DRIVER_GROUP_TOOLCHAIN}, 123 #endif 124 #if KIT_TOOL_IMAGE_ENABLED 125 {"image", driver_image, NULL, driver_help_image, 126 "Emit flat kernel/load images from linked objects", DRIVER_HELP_BINARY, 127 DRIVER_GROUP_TOOLCHAIN}, 128 #endif 129 #if KIT_TOOL_OBJDUMP_ENABLED 130 {"objdump", driver_objdump, NULL, driver_help_objdump, 131 "Dump sections, symbols, disassembly, hex, and relocations", 132 DRIVER_HELP_BINARY, DRIVER_GROUP_TOOLCHAIN}, 133 #endif 134 #if KIT_TOOL_RUN_ENABLED 135 {"run", driver_run, driver_run_ex, driver_help_run, 136 "JIT-compile inputs and invoke the entry symbol in-process", 137 DRIVER_HELP_EXECUTION, DRIVER_GROUP_OTHER}, 138 #endif 139 #if KIT_TOOL_DBG_ENABLED 140 {"dbg", driver_dbg, driver_dbg_ex, driver_help_dbg, 141 "Interactive JIT debugger (REPL on top of the JIT image)", 142 DRIVER_HELP_EXECUTION, DRIVER_GROUP_OTHER}, 143 #endif 144 #if KIT_TOOL_EMU_ENABLED 145 {"emu", driver_emu, NULL, driver_help_emu, NULL, DRIVER_HELP_EXECUTION, 146 DRIVER_GROUP_OTHER}, 147 #endif 148 #if KIT_TOOL_NM_ENABLED 149 {"nm", driver_nm, NULL, driver_help_nm, "List symbols from object files", 150 DRIVER_HELP_BINARY, DRIVER_GROUP_TOOLCHAIN}, 151 #endif 152 #if KIT_TOOL_SIZE_ENABLED 153 {"size", driver_size, NULL, driver_help_size, 154 "Display section sizes of object files", DRIVER_HELP_BINARY, 155 DRIVER_GROUP_TOOLCHAIN}, 156 #endif 157 #if KIT_TOOL_ADDR2LINE_ENABLED 158 {"addr2line", driver_addr2line, NULL, driver_help_addr2line, 159 "Translate addresses to file:line using debug info", DRIVER_HELP_BINARY, 160 DRIVER_GROUP_TOOLCHAIN}, 161 #endif 162 #if KIT_TOOL_SYMBOLIZE_ENABLED 163 {"symbolize", driver_symbolize, NULL, driver_help_symbolize, 164 "Annotate a kit backtrace stream with func at file:line", 165 DRIVER_HELP_BINARY, DRIVER_GROUP_OTHER}, 166 #endif 167 #if KIT_TOOL_STRINGS_ENABLED 168 {"strings", driver_strings, NULL, driver_help_strings, 169 "Print printable character sequences found in a file", DRIVER_HELP_BINARY, 170 DRIVER_GROUP_TOOLCHAIN}, 171 #endif 172 #if KIT_TOOL_CAS_ENABLED 173 {"cas", driver_cas, NULL, driver_help_cas, 174 "Store, inspect, verify, and materialize kit CAS blobs and trees", 175 DRIVER_HELP_DISTRIBUTION, DRIVER_GROUP_OTHER}, 176 #endif 177 #if KIT_TOOL_PKG_ENABLED 178 {"pkg", driver_pkg, NULL, driver_help_pkg, 179 "Bundle, sign, verify, and unpack distributable .kpkg packages", 180 DRIVER_HELP_DISTRIBUTION, DRIVER_GROUP_OTHER}, 181 #endif 182 #if KIT_TOOL_XXD_ENABLED 183 {"xxd", driver_xxd, NULL, driver_help_xxd, 184 "Hex dump any file (and reverse a dump back to binary)", DRIVER_HELP_DATA, 185 DRIVER_GROUP_BYTEUTIL}, 186 #endif 187 #if KIT_TOOL_CMP_ENABLED 188 {"cmp", driver_cmp, NULL, driver_help_cmp, "Compare two files byte by byte", 189 DRIVER_HELP_DATA, DRIVER_GROUP_BYTEUTIL}, 190 #endif 191 #if KIT_TOOL_HASH_ENABLED 192 {"hash", driver_hash, NULL, driver_help_hash, 193 "Hash files with SHA-256, BLAKE2b, or CRC-32", DRIVER_HELP_DATA, 194 DRIVER_GROUP_OTHER}, 195 {"sha256sum", driver_sha256sum, NULL, driver_help_sha256sum, 196 "SHA-256 of files or stdin (sha256sum-compatible)", DRIVER_HELP_DATA, 197 DRIVER_GROUP_BYTEUTIL}, 198 {"b2sum", driver_b2sum, NULL, driver_help_b2sum, 199 "BLAKE2b-256 of files or stdin (b2sum-style)", DRIVER_HELP_DATA, 200 DRIVER_GROUP_BYTEUTIL}, 201 {"crc32", driver_crc32, NULL, driver_help_crc32, "CRC-32 of files or stdin", 202 DRIVER_HELP_DATA, DRIVER_GROUP_BYTEUTIL}, 203 #endif 204 #if KIT_TOOL_COMPRESS_ENABLED 205 {"compress", driver_compress, NULL, driver_help_compress, 206 "Compress or decompress data (gzip, lz4 frame)", DRIVER_HELP_DATA, 207 DRIVER_GROUP_OTHER}, 208 {"gzip", driver_gzip, NULL, driver_help_gzip, 209 "Compress to gzip (.gz); -d to decompress", DRIVER_HELP_DATA, 210 DRIVER_GROUP_BYTEUTIL}, 211 {"gunzip", driver_gunzip, NULL, driver_help_gunzip, 212 "Decompress gzip (.gz) streams", DRIVER_HELP_DATA, DRIVER_GROUP_BYTEUTIL}, 213 {"lz4", driver_lz4, NULL, driver_help_lz4, 214 "Compress to LZ4 frame (.lz4); -d to decompress", DRIVER_HELP_DATA, 215 DRIVER_GROUP_BYTEUTIL}, 216 {"lz4c", driver_lz4c, NULL, driver_help_lz4c, 217 "Compress to LZ4 frame (.lz4) (lz4 alias)", DRIVER_HELP_DATA, 218 DRIVER_GROUP_BYTEUTIL}, 219 #endif 220 #if KIT_TOOL_DISAS_ENABLED 221 {"disas", driver_disas, NULL, driver_help_disas, 222 "Disassemble raw machine-code bytes for a target arch", DRIVER_HELP_BINARY, 223 DRIVER_GROUP_OTHER}, 224 #endif 225 #if KIT_TOOL_MC_ENABLED 226 {"mc", driver_mc, NULL, driver_help_mc, 227 "Assemble one instruction and show its machine-code encoding", 228 DRIVER_HELP_BINARY, DRIVER_GROUP_OTHER}, 229 #endif 230 #if KIT_TOOL_GRAM_ENABLED 231 {"gram", driver_gram, NULL, driver_help_gram, 232 "Generate a C parser/lexer from an EBNF grammar", DRIVER_HELP_BUILD, 233 DRIVER_GROUP_OTHER}, 234 #endif 235 #if KIT_TOOL_TARGETS_ENABLED 236 {"targets", driver_targets, NULL, driver_help_targets, 237 "List and inspect compiled target profiles", DRIVER_HELP_KIT, 238 DRIVER_GROUP_OTHER}, 239 #endif 240 {"version", driver_version_command, NULL, driver_help_version_command, 241 "Print canonical release/build/host identity", DRIVER_HELP_KIT, 0}, 242 #if KIT_TOOL_UPDATE_ENABLED 243 {"update", driver_update, NULL, driver_help_update, 244 "Verify and install a newer kit; manage installed versions", 245 DRIVER_HELP_KIT, DRIVER_GROUP_OTHER}, 246 #endif 247 {NULL, NULL, NULL, NULL, NULL, DRIVER_HELP_GROUP_COUNT, DRIVER_GROUP_OTHER}, 248 }; 249 250 unsigned driver_tool_count(void) { 251 return (unsigned)(sizeof driver_tools / sizeof driver_tools[0]) - 1u; 252 } 253 254 const char* driver_tool_name(unsigned index) { 255 if (index >= driver_tool_count()) return NULL; 256 return driver_tools[index].name; 257 } 258 259 unsigned driver_tool_groups(unsigned index) { 260 if (index >= driver_tool_count()) return 0u; 261 return driver_tools[index].groups; 262 } 263 264 int driver_tool_public(unsigned index) { 265 return index < driver_tool_count() && driver_tools[index].summary != NULL; 266 } 267 268 int driver_tool_find(const char* name) { 269 unsigned i; 270 if (!name) return -1; 271 for (i = 0; i < driver_tool_count(); ++i) { 272 if (driver_streq(name, driver_tools[i].name)) return (int)i; 273 } 274 return -1; 275 } 276 277 static const DriverToolDesc* find_tool(const char* name) { 278 unsigned i; 279 for (i = 0; i < driver_tool_count(); ++i) { 280 if (driver_streq(name, driver_tools[i].name)) return &driver_tools[i]; 281 } 282 return NULL; 283 } 284 285 static int dispatch(const char* name, int argc, char** argv, 286 const KitDriverExtension* ext) { 287 const DriverToolDesc* tool = find_tool(name); 288 if (tool) { 289 /* `--version` is answered uniformly for every tool here, before the tool's 290 * own argument parser runs, so it works for both the symlink form 291 * (argv[0] == "cc ... --version") and the subcommand form 292 * ("kit cc ... --version", which also routes through dispatch). The scan 293 * stops at "--", so a flag forwarded to a JITed program / guest is safe. 294 * `update` is exempt: there `--version <ver>` is a value-bearing flag 295 * (flip to an installed version), not a banner query, so the uniform 296 * shortcut would hijack it. */ 297 if (!driver_streq(tool->name, "update") && 298 driver_argv_wants_version(argc, argv)) { 299 driver_print_version(tool->name); 300 return 0; 301 } 302 if (tool->main_ex) return tool->main_ex(argc, argv, ext); 303 return tool->main(argc, argv); 304 } 305 return -1; 306 } 307 308 /* If `name` matches a tool, print its help and return 0. Otherwise return 309 * non-zero (caller reports the error). */ 310 static int print_tool_help(const char* name) { 311 const DriverToolDesc* tool = find_tool(name); 312 if (tool) { 313 tool->help(); 314 return 0; 315 } 316 return -1; 317 } 318 319 static void report_unknown_tool(const char* name) { 320 const char* candidates[64]; 321 DriverSuggestion suggestions[3]; 322 size_t candidate_count = 0; 323 size_t nsuggestions; 324 unsigned i; 325 for (i = 0; i < driver_tool_count() && candidate_count < 64; ++i) 326 candidates[candidate_count++] = driver_tools[i].name; 327 nsuggestions = driver_suggest_values(name, candidates, candidate_count, 328 suggestions, 3); 329 if (nsuggestions) 330 driver_errf("kit", "no such tool: %s; did you mean '%s'?", name, 331 suggestions[0].value); 332 else 333 driver_errf("kit", "no such tool: %s; run `kit --help` to list tools", 334 name); 335 } 336 337 int driver_is_help_flag(const char* arg) { 338 if (!arg) return 0; 339 return driver_streq(arg, "--help") || driver_streq(arg, "-help"); 340 } 341 342 int driver_argv_wants_help(int argc, char** argv, int accept_short_h) { 343 int i; 344 for (i = 1; i < argc; ++i) { 345 /* `--` ends the driver's own option scan: anything after it is 346 * forwarded to the JITed program (run/dbg) or the guest (emu), 347 * so a user's own `--help` to their program must not be hijacked. */ 348 if (driver_streq(argv[i], "--")) break; 349 if (driver_is_help_flag(argv[i])) return 1; 350 if (accept_short_h && driver_streq(argv[i], "-h")) return 1; 351 } 352 return 0; 353 } 354 355 int driver_argv_wants_version(int argc, char** argv) { 356 /* Only the FIRST argument a tool receives counts as a version query, so a 357 * sub-flag that legitimately spells --version (e.g. `pkg create --version 358 * 2026.6.0`, where --version is the package version) is never hijacked. The 359 * common forms `cc --version` and `kit cc --version` both arrive with 360 * --version as argv[1] of the dispatched tool. */ 361 return argc >= 2 && driver_streq(argv[1], "--version"); 362 } 363 364 void driver_print_version(const char* tool) { 365 if (tool) 366 driver_printf("kit %s %s (%s, %s)\n", tool, kit_version_string(), 367 kit_build_id(), kit_host_triple()); 368 else 369 driver_printf("kit %s (%s, %s)\n", kit_version_string(), kit_build_id(), 370 kit_host_triple()); 371 } 372 373 static void driver_help_version_command(void) { 374 driver_printf( 375 "kit version — print release/build/host identity\n" 376 "\n" 377 "USAGE\n" 378 " kit version\n" 379 " kit --version\n" 380 "\n" 381 "Both forms print byte-identical canonical version output. `version` is\n" 382 "an internal discovery command and is not installed as a multicall alias.\n" 383 "\n" 384 "OPTIONS\n" 385 " -h, --help show this help and exit\n" 386 "\n" 387 "EXIT CODES\n" 388 " 0 success 2 bad usage\n"); 389 } 390 391 static int driver_version_command(int argc, char** argv) { 392 if (driver_argv_wants_help(argc, argv, 1)) { 393 driver_help_version_command(); 394 return 0; 395 } 396 if (argc != 1) { 397 driver_errf("version", "unexpected argument: %s", argv[1]); 398 return 2; 399 } 400 driver_print_version(NULL); 401 return 0; 402 } 403 404 static const char* driver_help_group_name(DriverHelpGroup group) { 405 switch (group) { 406 case DRIVER_HELP_BUILD: 407 return "Compilation and build"; 408 case DRIVER_HELP_BINARY: 409 return "Binary and object tools"; 410 case DRIVER_HELP_EXECUTION: 411 return "Execution and debugging"; 412 case DRIVER_HELP_DISTRIBUTION: 413 return "Distribution"; 414 case DRIVER_HELP_DATA: 415 return "Data utilities"; 416 case DRIVER_HELP_KIT: 417 return "Kit management"; 418 case DRIVER_HELP_GROUP_COUNT: 419 break; 420 } 421 return NULL; 422 } 423 424 void driver_help_top(void) { 425 unsigned group; 426 unsigned i; 427 driver_printf( 428 "kit — standalone compilation, linking, execution, and binary toolkit\n" 429 "\n" 430 "USAGE\n" 431 " kit <tool> [args...] multi-call dispatch by name\n" 432 " <tool> [args...] when invoked via the tool's " 433 "symlink\n" 434 " kit help [<tool>] this help, or per-tool help\n" 435 " kit --version release/build/host identity\n" 436 "\n" 437 "TOOLS\n"); 438 for (group = 0; group < (unsigned)DRIVER_HELP_GROUP_COUNT; ++group) { 439 int heading_printed = 0; 440 for (i = 0; i < driver_tool_count(); ++i) { 441 if (!driver_tool_public(i) || 442 driver_tools[i].help_group != (DriverHelpGroup)group) 443 continue; 444 if (!heading_printed) { 445 driver_printf("\n %s\n", 446 driver_help_group_name((DriverHelpGroup)group)); 447 heading_printed = 1; 448 } 449 driver_printf(" %-9s %s\n", driver_tools[i].name, 450 driver_tools[i].summary); 451 } 452 } 453 driver_printf( 454 "\n" 455 "GETTING HELP\n" 456 " kit <tool> --help full per-tool help (also -h, except " 457 "objdump)\n" 458 " kit help <tool> same as `kit <tool> --help`\n" 459 " kit <tool> --version tool identity (except update, where\n" 460 " --version VER selects a release)\n" 461 "\n" 462 "NO-ARGUMENT BEHAVIOR\n" 463 " Operand-oriented tools usually show help. Stream filters may read\n" 464 " stdin, dbg enters its REPL, and a few operational tools act directly.\n" 465 " Each tool's page documents its stdin and output conventions.\n" 466 "\n" 467 "OUTPUT AND ENVIRONMENT\n" 468 " Requested help and normal data go to stdout; diagnostics go to stderr\n" 469 " unless a tool page says otherwise. Per-tool pages list relevant\n" 470 " environment variables, defaults, and state directories.\n" 471 "\n" 472 "EXIT CODES\n" 473 " 0 success\n" 474 " 1 tool-reported error (compile, link, I/O, ...)\n" 475 " 2 bad command-line usage\n" 476 " Execution tools may pass through another program exit status when\n" 477 " their own page says so.\n"); 478 } 479 480 int kit_driver_main_ex(int argc, char** argv, const KitDriverExtension* ext) { 481 const char* name; 482 char normalized_name[64]; 483 int rc; 484 485 if (argc < 1) return 2; 486 name = driver_basename(argv[0]); 487 488 /* Windows aliases use the executable suffix required by CreateProcess and 489 * PATHEXT (cc.exe, ld.exe, ...), while the centralized tool table stores 490 * suffix-free command names. Normalize only the final argv[0] component; 491 * ordinary command arguments such as `kit install cc.exe` stay strict. */ 492 { 493 size_t n = driver_strlen(name); 494 if (n > 4u && n - 4u < sizeof(normalized_name) && name[n - 4u] == '.' && 495 (name[n - 3u] == 'e' || name[n - 3u] == 'E') && 496 (name[n - 2u] == 'x' || name[n - 2u] == 'X') && 497 (name[n - 1u] == 'e' || name[n - 1u] == 'E')) { 498 driver_memcpy(normalized_name, name, n - 4u); 499 normalized_name[n - 4u] = '\0'; 500 name = normalized_name; 501 } 502 } 503 504 /* Multi-call form first: argv[0] is the tool name (e.g. installed as 505 * a `cc` symlink). Help inside the tool is gated by the tool itself. */ 506 rc = dispatch(name, argc, argv, ext); 507 if (rc != -1) return rc; 508 509 /* From here on argv[0] was the bare "kit" binary. Apply the 510 * top-level help / `help <tool>` routing before delegating. */ 511 if (argc < 2) { 512 driver_help_top(); 513 return 0; 514 } 515 516 if (driver_is_help_flag(argv[1]) || driver_streq(argv[1], "-h")) { 517 driver_help_top(); 518 return 0; 519 } 520 521 if (driver_streq(argv[1], "--version")) { 522 driver_print_version(NULL); 523 return 0; 524 } 525 526 if (driver_streq(argv[1], "help")) { 527 if (argc < 3) { 528 driver_help_top(); 529 return 0; 530 } 531 if (print_tool_help(argv[2]) == 0) return 0; 532 report_unknown_tool(argv[2]); 533 return 2; 534 } 535 536 { 537 char* tool_name = argv[1]; 538 argv[1] = argv[0]; 539 rc = dispatch(tool_name, argc - 1, argv + 1, ext); 540 argv[1] = tool_name; 541 if (rc != -1) return rc; 542 } 543 544 report_unknown_tool(argv[1]); 545 return 2; 546 } 547 548 int driver_main(int argc, char** argv) { return kit_driver_main_ex(argc, argv, NULL); } 549 550 #ifdef KIT_DRIVER_EXT_REGISTER 551 extern KitStatus KIT_DRIVER_EXT_REGISTER(KitFrontendRegistry*); 552 #endif 553 554 int main(int argc, char** argv) { 555 #ifdef KIT_DRIVER_EXT_REGISTER 556 KitDriverExtension ext; 557 ext.register_frontends = KIT_DRIVER_EXT_REGISTER; 558 return kit_driver_main_ex(argc, argv, &ext); 559 #else 560 return kit_driver_main_ex(argc, argv, NULL); 561 #endif 562 }