Status ws_new_pattern(SyntaxPattern **syn_pattern_ptr, const Regex *regex, SyntaxToken token) { assert(syn_pattern_ptr != NULL); assert(regex != NULL); assert(!is_null_or_empty(regex->regex_pattern)); SyntaxPattern *syn_pattern = malloc(sizeof(SyntaxPattern)); if (syn_pattern == NULL) { return OUT_OF_MEMORY("Unable to allocate SyntaxPattern"); } memset(syn_pattern, 0, sizeof(SyntaxPattern)); Status status = ru_compile_custom_error_msg(&syn_pattern->regex, regex, "pattern "); if (!STATUS_IS_SUCCESS(status)) { free(syn_pattern); return status; } syn_pattern->token = token; *syn_pattern_ptr = syn_pattern; return STATUS_SUCCESS; }
/* Run SyntaxDefintion against buffer substring to determine * tokens present and return these matches */ static SyntaxMatches *ws_generate_matches(const SyntaxDefinition *syn_def, const char *str, size_t str_len, /* Offset into buffer str was taken * from */ size_t offset) { assert(str != NULL); SyntaxMatches *syn_matches = sy_new_matches(offset); if (syn_matches == NULL || str_len == 0) { return syn_matches; } const WedSyntaxDefinition *wed_def = (WedSyntaxDefinition *)syn_def; const SyntaxPattern *pattern = wed_def->patterns; SyntaxMatch syn_match; RegexResult result; Status status; /* Run each SyntaxPattern against str */ while (pattern != NULL) { size_t offset = 0; /* Find all matches in str ensuring we don't * exceed MAX_SYNTAX_MATCH_NUM */ while (syn_matches->match_num < MAX_SYNTAX_MATCH_NUM && offset < str_len) { status = ru_exec(&result, &pattern->regex, str, str_len, offset); if (!(STATUS_IS_SUCCESS(status) && result.match)) { st_free_status(status); /* Failure or no matches in the remainder of str * so we're finished with this SyntaxPatten */ break; } syn_match.offset = result.output_vector[0]; syn_match.length = result.match_length; syn_match.token = pattern->token; ws_add_match(syn_matches, &syn_match); offset = result.output_vector[0] + result.match_length; } pattern = pattern->next; } /* Order matches by offset then length */ qsort(syn_matches->matches, syn_matches->match_num, sizeof(SyntaxMatch), ws_match_cmp); return syn_matches; }
/* TODO: don't malloc name - on the stack */ chc_status_t con_create(unsigned int fd, struct syd_obj **obj) { STATUS_INIT(status); int snprintf_result = 0; char *name = NULL; struct con_context *context = NULL; struct syd_obj *local_obj = NULL; if (NULL == obj) { STATUS_LABEL(status, CHC_CON_INVALID); goto cleanup; } context = (struct con_context *)vzalloc(sizeof(*context)); if (NULL == context) { STATUS_LABEL(status, CHC_CON_VZALLOC); goto cleanup; } context->fd = fd; name = (char *)vzalloc(sizeof(COR_MAX_NAME)); if (NULL == name) { STATUS_LABEL(status, CHC_CON_VZALLOC); goto cleanup; } /* TODO: validate null termination */ snprintf_result = snprintf(name, COR_MAX_NAME, CON_PATTERN, fd); if (0 > snprintf_result) { STATUS_LABEL(status, CHC_CON_SNPRINTF); goto cleanup; } local_obj = (struct syd_obj *)vzalloc(sizeof(*local_obj)); if (NULL == local_obj) { STATUS_LABEL(status, CHC_CON_VZALLOC); goto cleanup; } STATUS_ASSIGN(status, syd_create(name, context, &g_con_ops)); if (STATUS_IS_ERROR(status)) { goto cleanup; } STATUS_LABEL(status, CHC_SUCCESS); cleanup: if (STATUS_IS_SUCCESS(status)) { *obj = local_obj; } else { if (NULL != local_obj) { vfree(local_obj); } if (NULL != context) { vfree(context); } if (NULL != name) { vfree(name); } } return status; }
/* Interface to run prompt completion */ Status pc_run_prompt_completer(const Session *sess, Prompt *prompt, int reverse) { PromptType prompt_type = prompt->prompt_type; if (!pc_has_prompt_completer(prompt_type)) { return STATUS_SUCCESS; } pr_clear_suggestions(prompt); char *prompt_content = pr_get_prompt_content(prompt); size_t prompt_content_len = strlen(prompt_content); if (prompt_content_len == 0) { free(prompt_content); return STATUS_SUCCESS; } const PromptCompleterConfig *pcc = &pc_prompt_completers[prompt_type]; PromptCompleter completer = pcc->prompt_completer; Status status = completer(sess, prompt->suggestions, prompt_content, prompt_content_len); if (!STATUS_IS_SUCCESS(status) || pr_suggestion_num(prompt) == 0) { free(prompt_content); return status; } list_sort(prompt->suggestions, pc_suggestion_comparator); /* Add the inital input from the user to the list of suggestions * so that it can be cycled back to when all the suggestions have * been displayed */ PromptSuggestion *inital_input = pc_new_suggestion(prompt_content, SR_NO_MATCH, NULL); free(prompt_content); if (inital_input == NULL || !list_add(prompt->suggestions, inital_input)) { free(inital_input); return OUT_OF_MEMORY("Unable to allocated suggestions"); } /* At this point there should be at least one suggestion plus * the inital input */ assert(pr_suggestion_num(prompt) > 1); size_t start_index = 0; /* <S-Tab> can be used to reverse through the suggestions and * invoke prompt completion in reverse, so start from end of suggestion * list if necessary */ if (reverse) { start_index = pr_suggestion_num(prompt) - 2; } /* Update prompt content with first suggestion */ status = pr_show_suggestion(prompt, start_index); return status; }