/* Check if the given pattern matches part of the given trie, returning an * empty string on a partial initial match, a %NULL if there's no match in the * works, and the result string if we have an exact match. */ TRIE_MAYBE_STATIC const char * _vte_trie_match(struct _vte_trie *trie, const gunichar *pattern, gsize length, const char **res, const gunichar **consumed, GQuark *quark, GValueArray **array) { const char *ret = NULL; GQuark tmpquark; GValueArray *valuearray; GValue *value; const gunichar *dummyconsumed; gboolean greedy = FALSE; guint i; if (array != NULL && *array != NULL) { valuearray = *array; } else { valuearray = g_value_array_new(0); } if (quark == NULL) { quark = &tmpquark; } *quark = 0; if (consumed == NULL) { consumed = &dummyconsumed; } *consumed = pattern; ret = _vte_trie_matchx(trie, pattern, length, greedy, res, consumed, quark, valuearray); if (((ret == NULL) || (ret[0] == '\0')) || (valuearray->n_values == 0)){ if (valuearray != NULL) { for (i = 0; i < valuearray->n_values; i++) { value = g_value_array_get_nth(valuearray, i); if (G_VALUE_HOLDS_POINTER(value)) { g_free(g_value_get_pointer(value)); g_value_set_pointer(value, NULL); } } if (array == NULL || valuearray != *array) { _vte_matcher_free_params_array(NULL, valuearray); } } } else { if (array == NULL) { _vte_matcher_free_params_array(NULL, valuearray); } } return ret; }
int main(int argc, char **argv) { struct _vte_trie *trie; GValueArray *array = NULL; GQuark quark; gunichar buf[LINE_MAX]; const gunichar *consumed; gsize buflen; _vte_debug_init(); g_type_init(); trie = _vte_trie_new(); _vte_trie_add(trie, "abcdef", 6, "abcdef", g_quark_from_static_string("abcdef")); _vte_trie_add(trie, "abcde", 5, "abcde", g_quark_from_static_string("abcde")); _vte_trie_add(trie, "abcdeg", 6, "abcdeg", g_quark_from_static_string("abcdeg")); _vte_trie_add(trie, "abc%+Aeg", 8, "abc%+Aeg", g_quark_from_static_string("abc%+Aeg")); _vte_trie_add(trie, "abc%deg", 7, "abc%deg", g_quark_from_static_string("abc%deg")); _vte_trie_add(trie, "abc%%eg", 7, "abc%%eg", g_quark_from_static_string("abc%%eg")); _vte_trie_add(trie, "abc%%%i%deg", 11, "abc%%%i%deg", g_quark_from_static_string("abc%%%i%deg")); _vte_trie_add(trie, "<esc>[%i%d;%dH", 14, "vtmatch", g_quark_from_static_string("vtmatch")); _vte_trie_add(trie, "<esc>[%i%mL", 11, "multimatch", g_quark_from_static_string("multimatch")); _vte_trie_add(trie, "<esc>[%mL<esc>[%mL", 18, "greedy", g_quark_from_static_string("greedy")); _vte_trie_add(trie, "<esc>]2;%sh", 11, "decset-title", g_quark_from_static_string("decset-title")); printf("Wide encoding is `%s'.\n", VTE_CONV_GUNICHAR_TYPE); _vte_trie_print(trie); printf("\n"); quark = 0; convert_mbstowcs("abc", 3, buf, &buflen, sizeof(buf)); printf("`%s' = `%s'\n", "abc", _vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); printf("=> `%s' (%d)\n", g_quark_to_string(quark), (int)(consumed - buf)); if (array != NULL) { dump_array(array); _vte_matcher_free_params_array(NULL, array); array = NULL; } quark = 0; convert_mbstowcs("abcdef", 6, buf, &buflen, sizeof(buf)); printf("`%s' = `%s'\n", "abcdef", _vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); printf("=> `%s' (%d)\n", g_quark_to_string(quark), (int)(consumed - buf)); if (array != NULL) { dump_array(array); _vte_matcher_free_params_array(NULL, array); array = NULL; } quark = 0; convert_mbstowcs("abcde", 5, buf, &buflen, sizeof(buf)); printf("`%s' = `%s'\n", "abcde", _vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); printf("=> `%s' (%d)\n", g_quark_to_string(quark), (int)(consumed - buf)); if (array != NULL) { dump_array(array); _vte_matcher_free_params_array(NULL, array); array = NULL; } quark = 0; convert_mbstowcs("abcdeg", 6, buf, &buflen, sizeof(buf)); printf("`%s' = `%s'\n", "abcdeg", _vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); printf("=> `%s' (%d)\n", g_quark_to_string(quark), (int)(consumed - buf)); if (array != NULL) { dump_array(array); _vte_matcher_free_params_array(NULL, array); array = NULL; } quark = 0; convert_mbstowcs("abc%deg", 7, buf, &buflen, sizeof(buf)); printf("`%s' = `%s'\n", "abc%deg", _vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); printf("=> `%s' (%d)\n", g_quark_to_string(quark), (int)(consumed - buf)); if (array != NULL) { dump_array(array); _vte_matcher_free_params_array(NULL, array); array = NULL; } quark = 0; convert_mbstowcs("abc10eg", 7, buf, &buflen, sizeof(buf)); printf("`%s' = `%s'\n", "abc10eg", _vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); printf("=> `%s' (%d)\n", g_quark_to_string(quark), (int)(consumed - buf)); if (array != NULL) { dump_array(array); _vte_matcher_free_params_array(NULL, array); array = NULL; } quark = 0; convert_mbstowcs("abc%eg", 6, buf, &buflen, sizeof(buf)); printf("`%s' = `%s'\n", "abc%eg", _vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); printf("=> `%s' (%d)\n", g_quark_to_string(quark), (int)(consumed - buf)); if (array != NULL) { dump_array(array); _vte_matcher_free_params_array(NULL, array); array = NULL; } quark = 0; convert_mbstowcs("abc%10eg", 8, buf, &buflen, sizeof(buf)); printf("`%s' = `%s'\n", "abc%10eg", _vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); printf("=> `%s' (%d)\n", g_quark_to_string(quark), (int)(consumed - buf)); if (array != NULL) { dump_array(array); _vte_matcher_free_params_array(NULL, array); array = NULL; } quark = 0; convert_mbstowcs("abcBeg", 6, buf, &buflen, sizeof(buf)); printf("`%s' = `%s'\n", "abcBeg", _vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); printf("=> `%s' (%d)\n", g_quark_to_string(quark), (int)(consumed - buf)); if (array != NULL) { dump_array(array); _vte_matcher_free_params_array(NULL, array); array = NULL; } quark = 0; convert_mbstowcs("<esc>[25;26H", 12, buf, &buflen, sizeof(buf)); printf("`%s' = `%s'\n", "<esc>[25;26H", _vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); printf("=> `%s' (%d)\n", g_quark_to_string(quark), (int)(consumed - buf)); if (array != NULL) { dump_array(array); _vte_matcher_free_params_array(NULL, array); array = NULL; } quark = 0; convert_mbstowcs("<esc>[25;2", 10, buf, &buflen, sizeof(buf)); printf("`%s' = `%s'\n", "<esc>[25;2", _vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); printf("=> `%s' (%d)\n", g_quark_to_string(quark), (int)(consumed - buf)); if (array != NULL) { dump_array(array); _vte_matcher_free_params_array(NULL, array); } quark = 0; convert_mbstowcs("<esc>[25L", 9, buf, &buflen, sizeof(buf)); printf("`%s' = `%s'\n", "<esc>[25L", _vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); printf("=> `%s' (%d)\n", g_quark_to_string(quark), (int)(consumed - buf)); if (array != NULL) { dump_array(array); _vte_matcher_free_params_array(NULL, array); } quark = 0; convert_mbstowcs("<esc>[25L<esc>[24L", 18, buf, &buflen, sizeof(buf)); printf("`%s' = `%s'\n", "<esc>[25L<esc>[24L", _vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); printf("=> `%s' (%d)\n", g_quark_to_string(quark), (int)(consumed - buf)); if (array != NULL) { dump_array(array); _vte_matcher_free_params_array(NULL, array); } quark = 0; convert_mbstowcs("<esc>[25;26L", 12, buf, &buflen, sizeof(buf)); printf("`%s' = `%s'\n", "<esc>[25;26L", _vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); printf("=> `%s' (%d)\n", g_quark_to_string(quark), (int)(consumed - buf)); if (array != NULL) { dump_array(array); _vte_matcher_free_params_array(NULL, array); } quark = 0; convert_mbstowcs("<esc>]2;WoofWoofh", 17, buf, &buflen, sizeof(buf)); printf("`%s' = `%s'\n", "<esc>]2;WoofWoofh", _vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); printf("=> `%s' (%d)\n", g_quark_to_string(quark), (int)(consumed - buf)); if (array != NULL) { dump_array(array); _vte_matcher_free_params_array(NULL, array); array = NULL; } quark = 0; convert_mbstowcs("<esc>]2;WoofWoofh<esc>]2;WoofWoofh", 34, buf, &buflen, sizeof(buf)); printf("`%s' = `%s'\n", "<esc>]2;WoofWoofh<esc>]2;WoofWoofh", _vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); printf("=> `%s' (%d)\n", g_quark_to_string(quark), (int)(consumed - buf)); if (array != NULL) { dump_array(array); _vte_matcher_free_params_array(NULL, array); array = NULL; } quark = 0; convert_mbstowcs("<esc>]2;WoofWoofhfoo", 20, buf, &buflen, sizeof(buf)); printf("`%s' = `%s'\n", "<esc>]2;WoofWoofhfoo", _vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); printf("=> `%s' (%d)\n", g_quark_to_string(quark), (int)(consumed - buf)); if (array != NULL) { dump_array(array); _vte_matcher_free_params_array(NULL, array); array = NULL; } _vte_trie_free(trie); return 0; }
/* Check if the given pattern matches part of the given trie, returning an * empty string on a partial initial match, a %NULL if there's no match in the * works, and the result string if we have an exact match. */ static const char * _vte_trie_matchx(struct _vte_trie *trie, const gunichar *pattern, gsize length, gboolean greedy, const char **res, const gunichar **consumed, GQuark *quark, GValueArray *array) { unsigned int i; const char *hres; enum cclass cc; const char *best = NULL; GValueArray *bestarray = NULL; GQuark bestquark = 0; const gunichar *bestconsumed = pattern; /* Make sure that attempting to save output values doesn't kill us. */ if (res == NULL) { res = &hres; } /* Trivial cases. We've matched an entire pattern, or we're out of * pattern to match. */ if (trie->result != NULL) { *res = trie->result; *quark = trie->quark; *consumed = pattern; return *res; } if (length <= 0) { if (trie->trie_path_count > 0) { *res = ""; *quark = g_quark_from_static_string(""); *consumed = pattern; return *res; } else { *res = NULL; *quark = 0; *consumed = pattern; return *res; } } /* Now figure out which (if any) subtrees to search. First, see * which character class this character matches. */ for (cc = exact; cc < invalid; cc++) for (i = 0; i < trie->trie_path_count; i++) { struct _vte_trie *subtrie = trie->trie_paths[i].trie; struct char_class *cclass = trie->trie_paths[i].cclass; struct char_class_data *data = &trie->trie_paths[i].data; if (trie->trie_paths[i].cclass->type == cc) { /* If it matches this character class... */ if (cclass->check(pattern[0], data)) { const gunichar *prospect = pattern + 1; const char *tmp; GQuark tmpquark = 0; GValueArray *tmparray; gboolean better = FALSE; /* Move past characters which might match this * part of the string... */ while (cclass->multiple && ((gsize)(prospect - pattern) < length) && cclass->check(prospect[0], data)) { prospect++; } /* ... see if there's a parameter here, ... */ tmparray = g_value_array_new(0); cclass->extract(pattern, prospect - pattern, data, tmparray); /* ... and check if the subtree matches the * rest of the input string. Any parameters * further on will be appended to the array. */ _vte_trie_matchx(subtrie, prospect, length - (prospect - pattern), greedy, &tmp, consumed, &tmpquark, tmparray); /* If we haven't seen any matches yet, go ahead * and go by this result. */ if (best == NULL) { better = TRUE; } else /* If we have a match, and we didn't have one * already, go by this result. */ if ((best != NULL) && (best[0] == '\0') && (tmp != NULL) && (tmp[0] != '\0')) { better = TRUE; } else /* If we already have a match, and this one's * better (longer if we're greedy, shorter if * we're not), then go by this result. */ if ((tmp != NULL) && (tmp[0] != '\0') && (bestconsumed != NULL) && (consumed != NULL) && (*consumed != NULL)) { if (greedy && (bestconsumed < *consumed)) { better = TRUE; } else if (!greedy && (bestconsumed > *consumed)) { better = TRUE; } } if (better) { best = tmp; if (bestarray != NULL) { _vte_matcher_free_params_array( NULL, bestarray); } bestarray = tmparray; bestquark = tmpquark; bestconsumed = *consumed; } else { _vte_matcher_free_params_array( NULL, tmparray); tmparray = NULL; } } } } /* We're done searching. Copy out any parameters we picked up. */ if (bestarray != NULL) { for (i = 0; i < bestarray->n_values; i++) { GValue *value = g_value_array_get_nth(bestarray, i); g_value_array_append(array, value); if (G_VALUE_HOLDS_POINTER(value)) { g_value_set_pointer(value, NULL); } } _vte_matcher_free_params_array(NULL, bestarray); } #if 0 printf("`%s' ", best); dump_array(array); #endif *quark = bestquark; *res = best; *consumed = bestconsumed; return *res; }
int main(int argc, char **argv) { struct _vte_matcher *matcher = NULL; GArray *array; unsigned int i, j; int l; unsigned char buf[4096]; GValue *value; int infile; struct _vte_iso2022_state *subst; const char *tmp; GValueArray *values; _vte_debug_init(); if (argc < 1) { g_print("usage: %s [file]\n", argv[0]); return 1; } if ((argc > 1) && (strcmp(argv[1], "-") != 0)) { infile = open (argv[1], O_RDONLY); if (infile == -1) { g_print("error opening %s: %s\n", argv[1], strerror(errno)); exit(1); } } else { infile = 1; } g_type_init(); array = g_array_new(FALSE, FALSE, sizeof(gunichar)); matcher = _vte_matcher_new(); subst = _vte_iso2022_state_new(NULL, VTE_ISO2022_DEFAULT_UTF8_AMBIGUOUS_WIDTH, NULL, NULL); for (;;) { l = read (infile, buf, sizeof (buf)); if (!l) break; if (l == -1) { if (errno == EAGAIN) continue; exit (1); } g_array_set_size (array, 0); _vte_iso2022_process(subst, buf, (unsigned int) l, array); i = 0; while (i <= array->len) { tmp = NULL; values = NULL; for (j = 1; j < (array->len - i); j++) { _vte_matcher_match(matcher, &g_array_index(array, gunichar, i), j, &tmp, NULL, &values); if ((tmp == NULL) || (strlen(tmp) > 0)) { break; } } if (i + j == array->len) { break; } if (tmp == NULL) { gunichar c; c = g_array_index(array, gunichar, i); if (VTE_ISO2022_HAS_ENCODED_WIDTH(c)) { c &= ~VTE_ISO2022_ENCODED_WIDTH_MASK; } if (c < 32) { g_print("`^%c'\n", c + 64); } else if (c < 127) { g_print("`%c'\n", c); } else { g_print("`0x%x'\n", c); } i++; continue; } l = j; g_print("%s(", tmp); for (j = 0; (values != NULL) && (j < values->n_values); j++) { if (j > 0) { g_print(", "); } value = g_value_array_get_nth(values, j); if (G_VALUE_HOLDS_LONG(value)) { g_print("%ld", g_value_get_long(value)); } if (G_VALUE_HOLDS_STRING(value)) { g_print("`%s'", g_value_get_string(value)); } if (G_VALUE_HOLDS_POINTER(value)) { g_print("`%ls'", (wchar_t*) g_value_get_pointer(value)); } } if (values != NULL) { _vte_matcher_free_params_array(matcher, values); } g_print(")\n"); i += l; } } g_print("End of data.\n"); close (infile); _vte_iso2022_state_free(subst); g_array_free(array, TRUE); _vte_matcher_free(matcher); return 0; }