| 9572 | } |
| 9573 | |
| 9574 | static char *handle_search_code(cbm_mcp_server_t *srv, const char *args) { |
| 9575 | char *pattern = cbm_mcp_get_string_arg(args, "pattern"); |
| 9576 | char *project = get_project_arg(args); |
| 9577 | char *file_pattern = cbm_mcp_get_string_arg(args, "file_pattern"); |
| 9578 | char *path_filter = cbm_mcp_get_string_arg(args, "path_filter"); |
| 9579 | char *mode_str = cbm_mcp_get_string_arg(args, "mode"); |
| 9580 | int limit = cbm_mcp_get_int_arg(args, "limit", MCP_DEFAULT_LIMIT); |
| 9581 | int context_lines = cbm_mcp_get_int_arg(args, "context", 0); |
| 9582 | bool use_regex = cbm_mcp_get_bool_arg(args, "regex"); |
| 9583 | uint64_t search_t0 = cbm_now_ms(); |
| 9584 | /* In literal (non-regex) mode a '|' is matched as a byte, not alternation — |
| 9585 | * a common silent 0-match trap; flagged in the result warnings (#282). */ |
| 9586 | bool pat_has_pipe = pattern && strchr(pattern, '|') != NULL; |
| 9587 | |
| 9588 | int mode = parse_search_mode(mode_str); |
| 9589 | free(mode_str); |
| 9590 | |
| 9591 | cbm_regex_t path_regex; |
| 9592 | bool has_path_filter = compile_path_filter(path_filter, &path_regex); |
| 9593 | free(path_filter); |
| 9594 | path_filter = NULL; |
| 9595 | |
| 9596 | if (!pattern) { |
| 9597 | free(project); |
| 9598 | free(file_pattern); |
| 9599 | return cbm_mcp_text_result("pattern is required", true); |
| 9600 | } |
| 9601 | |
| 9602 | /* Project is required */ |
| 9603 | if (!project) { |
| 9604 | free(pattern); |
| 9605 | free(file_pattern); |
| 9606 | char *_err = build_project_list_error("project is required"); |
| 9607 | char *_res = cbm_mcp_text_result(_err, true); |
| 9608 | free(_err); |
| 9609 | return _res; |
| 9610 | } |
| 9611 | |
| 9612 | char *root_path = get_project_root(srv, project); |
| 9613 | if (!root_path) { |
| 9614 | free(pattern); |
| 9615 | free(project); |
| 9616 | free(file_pattern); |
| 9617 | char *_err = build_project_list_error("project not found or not indexed"); |
| 9618 | char *_res = cbm_mcp_text_result(_err, true); |
| 9619 | free(_err); |
| 9620 | return _res; |
| 9621 | } |
| 9622 | |
| 9623 | if (!validate_search_args(root_path, file_pattern)) { |
| 9624 | if (has_path_filter) { |
| 9625 | cbm_regfree(&path_regex); |
| 9626 | } |
| 9627 | free(root_path); |
| 9628 | free(pattern); |
| 9629 | free(project); |
| 9630 | free(file_pattern); |
| 9631 | return cbm_mcp_text_result("path or file_pattern contains invalid characters", true); |
no test coverage detected