int main(int argc, char **argv) { struct _vte_table *table; int i; const char *candidates[] = { "ABCD", "ABCDEF", "]2;foo", "]3;foo", "]3;fook", "[3;foo", "[3;3m", "[3;3mk", "[3;3hk", "[3;3h", "]3;3h", "[3;3k", "[3;3kj", "s", }; const char *result, *p; const gunichar *consumed; char *tmp; gunichar *candidate; GQuark quark; GValueArray *array; g_type_init(); table = _vte_table_new(); _vte_table_add(table, "ABCDEFG", 7, "ABCDEFG", 0); _vte_table_add(table, "ABCD", 4, "ABCD", 0); _vte_table_add(table, "ABCDEFH", 7, "ABCDEFH", 0); _vte_table_add(table, "ACDEFH", 6, "ACDEFH", 0); _vte_table_add(table, "ACDEF%sJ", 8, "ACDEF%sJ", 0); _vte_table_add(table, "ACDEF%i%mJ", 10, "ACDEF%dJ", 0); _vte_table_add(table, "[%mh", 5, "move-cursor", 0); _vte_table_add(table, "[%d;%d;%dm", 11, "set-graphic-rendition", 0); _vte_table_add(table, "[%dm", 5, "set-graphic-rendition", 0); _vte_table_add(table, "[m", 3, "set-graphic-rendition", 0); _vte_table_add(table, "]3;%s", 7, "set-icon-title", 0); _vte_table_add(table, "]4;%s", 7, "set-window-title", 0); printf("Table contents:\n"); _vte_table_print(table); printf("\nTable matches:\n"); for (i = 0; i < G_N_ELEMENTS(candidates); i++) { p = candidates[i]; candidate = make_wide(p); array = NULL; _vte_table_match(table, candidate, strlen(p), &result, &consumed, &quark, &array); tmp = escape(p); printf("`%s' => `%s'", tmp, (result ? result : "(NULL)")); g_free(tmp); print_array(array); printf(" (%d chars)\n", (int) (consumed ? consumed - candidate: 0)); g_free(candidate); } _vte_table_free(table); return 0; }
static void _vte_table_addi(struct _vte_table *table, const unsigned char *original, gssize original_length, const char *pattern, gssize length, const char *result) { int i; guint8 check; struct _vte_table *subtable; if (original_length == -1) { original_length = strlen((char *) original); } if (length == -1) { length = strlen(pattern); } /* If this is the terminal node, set the result. */ if (length == 0) { if (table->result != NULL) _vte_debug_print (VTE_DEBUG_PARSE, "`%s' and `%s' are indistinguishable.\n", table->result, result); table->result = g_intern_string(result); if (table->original != NULL) { g_free(table->original); } table->original = g_memdup(original, original_length); table->original_length = original_length; return; } /* All of the interesting arguments begin with '%'. */ if (pattern[0] == '%') { /* Handle numeric parameters. */ if (pattern[1] == 'd') { /* Create a new subtable. */ if (table->table_number == NULL) { subtable = _vte_table_new(); table->table_number = subtable; } else { subtable = table->table_number; } /* Add the rest of the string to the subtable. */ _vte_table_addi(subtable, original, original_length, pattern + 2, length - 2, result); return; } /* Handle variable-length parameters. */ if (pattern[1] == 'm') { /* Build the "new" original using the initial portion * of the original string and what's left after this * specifier. */ { int initial; GByteArray *b; initial = original_length - length; b = g_byte_array_new(); g_byte_array_set_size(b, 0); g_byte_array_append(b, original, initial); g_byte_array_append(b, (const guint8*)pattern + 2, length - 2); _vte_table_addi(table, b->data, b->len, (const char *)b->data + initial, b->len - initial, result); g_byte_array_free(b, TRUE); } /* Create a new subtable. */ if (table->table_number_list == NULL) { subtable = _vte_table_new(); table->table_number_list = subtable; } else { subtable = table->table_number_list; } /* Add the rest of the string to the subtable. */ _vte_table_addi(subtable, original, original_length, pattern + 2, length - 2, result); return; } /* Handle string parameters. */ if (pattern[1] == 's') { /* It must have a terminator. */ g_assert(length >= 3); /* Create a new subtable. */ if (table->table_string == NULL) { subtable = _vte_table_new(); table->table_string = subtable; } else { subtable = table->table_string; } /* Add the rest of the string to the subtable. */ _vte_table_addi(subtable, original, original_length, pattern + 2, length - 2, result); return; } /* Handle an escaped '%'. */ if (pattern[1] == '%') { /* Create a new subtable. */ if (table->table == NULL) { table->table = _vte_table_literal_new(); subtable = _vte_table_new(); table->table['%'] = subtable; } else if (table->table['%'] == NULL) { subtable = _vte_table_new(); table->table['%'] = subtable; } else { subtable = table->table['%']; } /* Add the rest of the string to the subtable. */ _vte_table_addi(subtable, original, original_length, pattern + 2, length - 2, result); return; } /* Handle a parameter character. */ if (pattern[1] == '+') { /* It must have an addend. */ g_assert(length >= 3); /* Fill in all of the table entries above the given * character value. */ for (i = pattern[2]; i < VTE_TABLE_MAX_LITERAL; i++) { /* Create a new subtable. */ if (table->table == NULL) { table->table = _vte_table_literal_new(); subtable = _vte_table_new(); table->table[i] = subtable; } else if (table->table[i] == NULL) { subtable = _vte_table_new(); table->table[i] = subtable; } else { subtable = table->table[i]; } /* Add the rest of the string to the subtable. */ _vte_table_addi(subtable, original, original_length, pattern + 3, length - 3, result); } /* Also add a subtable for higher characters. */ if (table->table == NULL) { table->table = _vte_table_literal_new(); subtable = _vte_table_new(); table->table[0] = subtable; } else if (table->table[0] == NULL) { subtable = _vte_table_new(); table->table[0] = subtable; } else { subtable = table->table[0]; } /* Add the rest of the string to the subtable. */ _vte_table_addi(subtable, original, original_length, pattern + 3, length - 3, result); return; } } /* A literal (or an unescaped '%', which is also a literal). */ check = (guint8) pattern[0]; g_assert(check < VTE_TABLE_MAX_LITERAL); if (table->table == NULL) { table->table = _vte_table_literal_new(); subtable = _vte_table_new(); table->table[check] = subtable; } else if (table->table[check] == NULL) { subtable = _vte_table_new(); table->table[check] = subtable; } else { subtable = table->table[check]; } /* Add the rest of the string to the subtable. */ _vte_table_addi(subtable, original, original_length, pattern + 1, length - 1, result); }