[gtk/wip/compose-parser: 6/15] composetable: Handle includes
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/compose-parser: 6/15] composetable: Handle includes
- Date: Wed, 14 Jul 2021 02:05:57 +0000 (UTC)
commit fb6c8cd466de50a7cc8b9e7642f7296a887a90a5
Author: Matthias Clasen <mclasen redhat com>
Date: Wed Jul 7 10:47:17 2021 -0400
composetable: Handle includes
This adds the mechanics for parsing include lines in
Compose files. We do detect and prevent cycles.
Tests included.
gtk/gtkcomposetable.c | 90 +++++++++++++++++++++++++++++++++-
testsuite/gtk/compose/cycle | 3 ++
testsuite/gtk/compose/include | 3 ++
testsuite/gtk/compose/include.expected | 4 ++
testsuite/gtk/compose/included | 1 +
testsuite/gtk/compose/nofile | 3 ++
testsuite/gtk/composetable.c | 47 ++++++++++++++++++
7 files changed, 149 insertions(+), 2 deletions(-)
---
diff --git a/gtk/gtkcomposetable.c b/gtk/gtkcomposetable.c
index 0c1f2d83f1..b8561aa161 100644
--- a/gtk/gtkcomposetable.c
+++ b/gtk/gtkcomposetable.c
@@ -49,6 +49,7 @@ gtk_compose_data_free (GtkComposeData *compose_data)
typedef struct {
GList *sequences;
+ GList *files;
const char *compose_file;
} GtkComposeParser;
@@ -60,6 +61,7 @@ parser_new (void)
parser = g_new (GtkComposeParser, 1);
parser->sequences = NULL;
+ parser->files = NULL;
parser->compose_file = NULL;
return parser;
@@ -69,6 +71,7 @@ static void
parser_free (GtkComposeParser *parser)
{
g_list_free_full (parser->sequences, (GDestroyNotify) gtk_compose_data_free);
+ g_list_free_full (parser->files, g_free);
g_free (parser);
}
@@ -248,6 +251,57 @@ fail:
return FALSE;
}
+static void parser_parse_file (GtkComposeParser *parser,
+ const char *path);
+
+static void
+parser_handle_include (GtkComposeParser *parser,
+ const char *line)
+{
+ const char *p;
+ const char *start, *end;
+ char *path;
+
+ p = line + strlen ("include ");
+
+ while (g_ascii_isspace (*p))
+ p++;
+
+ if (*p != '"')
+ goto error;
+
+ p++;
+
+ start = p;
+
+ while (*p && *p != '"')
+ p++;
+
+ if (*p != '"')
+ goto error;
+
+ end = p;
+
+ p++;
+
+ while (g_ascii_isspace (*p))
+ p++;
+
+ if (*p && *p != '#')
+ goto error;
+
+ path = g_strndup (start, end - start);
+
+ parser_parse_file (parser, path);
+
+ g_free (path);
+
+ return;
+
+error:
+ g_warning ("Could not parse include: %s", line);
+}
+
static void
parser_parse_line (GtkComposeParser *parser,
const char *line)
@@ -259,7 +313,10 @@ parser_parse_line (GtkComposeParser *parser,
return;
if (g_str_has_prefix (line, "include "))
- return;
+ {
+ parser_handle_include (parser, line);
+ return;
+ }
components = g_strsplit (line, ":", 2);
@@ -797,15 +854,44 @@ gtk_compose_table_new_with_list (GList *compose_list,
return retval;
}
+static char *
+canonicalize_filename (const char *path)
+{
+ GFile *file;
+ char *retval;
+
+ file = g_file_new_for_path (path);
+ retval = g_file_get_path (file);
+
+ g_object_unref (file);
+
+ return retval;
+}
+
static void
parser_parse_file (GtkComposeParser *parser,
const char *compose_file)
{
+ char *path;
+
// stash the name for the table hash
if (parser->compose_file == NULL)
parser->compose_file = compose_file;
- parser_read_file (parser, compose_file);
+ path = canonicalize_filename (compose_file);
+
+ if (g_list_find_custom (parser->files, path, (GCompareFunc)strcmp))
+ {
+ g_warning ("include cycle detected: %s", compose_file);
+ g_free (path);
+ return;
+ }
+
+ parser->files = g_list_prepend (parser->files, path);
+
+ parser_read_file (parser, path);
+
+ parser->files = g_list_remove (parser->files, path);
}
static GtkComposeTable *
diff --git a/testsuite/gtk/compose/cycle b/testsuite/gtk/compose/cycle
new file mode 100644
index 0000000000..b65eca834f
--- /dev/null
+++ b/testsuite/gtk/compose/cycle
@@ -0,0 +1,3 @@
+include "testsuite/gtk/compose/cycle" # create an include cycle
+
+<Multi_key> <s> <e> <q> : "!"
diff --git a/testsuite/gtk/compose/include b/testsuite/gtk/compose/include
new file mode 100644
index 0000000000..a4769355a4
--- /dev/null
+++ b/testsuite/gtk/compose/include
@@ -0,0 +1,3 @@
+include "testsuite/gtk/compose/included" # see if this works
+
+<Multi_key> <s> <e> <q> : "!"
diff --git a/testsuite/gtk/compose/include.expected b/testsuite/gtk/compose/include.expected
new file mode 100644
index 0000000000..10fbc4418c
--- /dev/null
+++ b/testsuite/gtk/compose/include.expected
@@ -0,0 +1,4 @@
+# n_seqs: 2
+# max_seq_len: 4
+<Uff20> <U73> <U61> <U73> : "\"\\"
+<Uff20> <U73> <U65> <U71> : "!" # U21
diff --git a/testsuite/gtk/compose/included b/testsuite/gtk/compose/included
new file mode 100644
index 0000000000..0d29359189
--- /dev/null
+++ b/testsuite/gtk/compose/included
@@ -0,0 +1 @@
+<Multi_key> <s> <a> <s> : "\"\\"
diff --git a/testsuite/gtk/compose/nofile b/testsuite/gtk/compose/nofile
new file mode 100644
index 0000000000..0b676e16d6
--- /dev/null
+++ b/testsuite/gtk/compose/nofile
@@ -0,0 +1,3 @@
+include "testsuite/gtk/compose/nosuchfile" # this file does not exist
+
+<Multi_key> <s> <e> <q> : "!"
diff --git a/testsuite/gtk/composetable.c b/testsuite/gtk/composetable.c
index 4348dfbea0..1414a7c99f 100644
--- a/testsuite/gtk/composetable.c
+++ b/testsuite/gtk/composetable.c
@@ -117,6 +117,50 @@ compose_table_compare (gconstpointer data)
g_free (expected);
}
+static void
+compose_table_cycle (void)
+{
+ if (g_test_subprocess ())
+ {
+ char *file;
+ GtkComposeTable *table;
+
+ file = g_build_filename (g_test_get_dir (G_TEST_DIST), "compose", "cycle", NULL);
+
+ table = gtk_compose_table_new_with_file (file);
+ g_assert_nonnull (table);
+ g_free (file);
+
+ return;
+ }
+
+ g_test_trap_subprocess (NULL, 0, 0);
+ g_test_trap_assert_stderr ("*include cycle detected*");
+ g_test_trap_assert_failed ();
+}
+
+static void
+compose_table_nofile (void)
+{
+ if (g_test_subprocess ())
+ {
+ char *file;
+ GtkComposeTable *table;
+
+ file = g_build_filename (g_test_get_dir (G_TEST_DIST), "compose", "nofile", NULL);
+
+ table = gtk_compose_table_new_with_file (file);
+ g_assert_nonnull (table);
+ g_free (file);
+
+ return;
+ }
+
+ g_test_trap_subprocess (NULL, 0, 0);
+ g_test_trap_assert_stderr ("*No such file or directory*");
+ g_test_trap_assert_failed ();
+}
+
/* Check matching against a small table */
static void
compose_table_match (void)
@@ -360,6 +404,9 @@ main (int argc, char *argv[])
g_test_add_data_func ("/compose-table/codepoint", "codepoint", compose_table_compare);
g_test_add_data_func ("/compose-table/multi", "multi", compose_table_compare);
g_test_add_data_func ("/compose-table/strings", "strings", compose_table_compare);
+ g_test_add_data_func ("/compose-table/include", "include", compose_table_compare);
+ g_test_add_func ("/compose-table/include-cycle", compose_table_cycle);
+ g_test_add_func ("/compose-table/include-nofile", compose_table_nofile);
g_test_add_func ("/compose-table/match", compose_table_match);
g_test_add_func ("/compose-table/match-compact", compose_table_match_compact);
g_test_add_func ("/compose-table/match-algorithmic", match_algorithmic);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]