From e7f62f69f37cfee2b0c75cdd5eed43dbb04219bd Mon Sep 17 00:00:00 2001 From: Jehan Date: Wed, 14 Aug 2024 15:48:37 +0200 Subject: [PATCH] tools: proper error handling for gen-languages. In particular, we don't want the build to succeed when various obvious issues occur, which may even end up in a successful-looking build (yet with no proper language lists), like we had in !1597. --- tools/gen-languages.c | 122 ++++++++++++++++++++++++++++-------------- 1 file changed, 83 insertions(+), 39 deletions(-) diff --git a/tools/gen-languages.c b/tools/gen-languages.c index 1b5ddd311b..bbfb1343ce 100644 --- a/tools/gen-languages.c +++ b/tools/gen-languages.c @@ -34,6 +34,13 @@ #include "gimp-intl.h" +#define PRINT(...) if (! g_output_stream_printf (output, NULL, NULL, &error, __VA_ARGS__))\ + {\ + g_printerr ("ERROR: %s\n", error->message);\ + g_object_unref (output);\ + exit (EXIT_FAILURE);\ + } + typedef enum { @@ -52,7 +59,7 @@ typedef struct } IsoCodesParser; -static void gimp_language_store_parser_init (void); +static gboolean gimp_language_store_parser_init (GError **error); static void gimp_language_store_parser_clean (void); static gboolean parse_iso_codes (GHashTable *base_lang_list, @@ -118,46 +125,48 @@ main (int argc, * along with this program. If not, see .\n\ */\n"; + if (! gimp_language_store_parser_init (&error)) + { + g_printerr ("ERROR: %s\n", error->message); + exit (EXIT_FAILURE); + } + outfile = g_file_new_build_filename (argv[0], "../../app/widgets/gimplanguagestore-data.h", NULL); output = G_OUTPUT_STREAM (g_file_replace (outfile, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &error)); g_object_unref (outfile); - g_output_stream_printf (output, NULL, NULL, &error, "%s", license_header); - g_output_stream_printf (output, NULL, NULL, &error, - "\n/* NOTE: this file is auto-generated by %s */\n\n", argv[0]); - gimp_language_store_parser_init (); + if (! output) + { + g_printerr ("ERROR: %s\n", error->message); + g_object_unref (output); + exit (EXIT_FAILURE); + } + + PRINT ("%s", license_header); + PRINT ("\n/* NOTE: this file is auto-generated by %s */\n\n", argv[0]); g_hash_table_iter_init (&lang_iter, l10n_lang_list); - g_output_stream_printf (output, NULL, NULL, &error, - "#define GIMP_L10N_LANGS_SIZE %d\n", g_hash_table_size (l10n_lang_list)); - g_output_stream_printf (output, NULL, NULL, &error, - "#define GIMP_ALL_LANGS_SIZE %d\n", g_hash_table_size (all_lang_list)); - g_output_stream_printf (output, NULL, NULL, &error, - "\ntypedef struct" - "\n{" - "\n gchar *code;" - "\n gchar *name;" - "\n} GimpLanguageDef;\n"); + PRINT ("#define GIMP_L10N_LANGS_SIZE %d\n", g_hash_table_size (l10n_lang_list)); + PRINT ("#define GIMP_ALL_LANGS_SIZE %d\n", g_hash_table_size (all_lang_list)); + PRINT ("\ntypedef struct" + "\n{" + "\n gchar *code;" + "\n gchar *name;" + "\n} GimpLanguageDef;\n"); - g_output_stream_printf (output, NULL, NULL, &error, - "\nstatic const GimpLanguageDef GimpL10nLanguages[GIMP_L10N_LANGS_SIZE] =" - "\n{\n"); + PRINT ("\nstatic const GimpLanguageDef GimpL10nLanguages[GIMP_L10N_LANGS_SIZE] =\n{\n"); while (g_hash_table_iter_next (&lang_iter, &code, &name)) - g_output_stream_printf (output, NULL, NULL, &error, - " { \"%s\", \"%s\" },\n", (gchar *) code, (gchar *) name); - g_output_stream_printf (output, NULL, NULL, &error, "};\n"); + PRINT (" { \"%s\", \"%s\" },\n", (gchar *) code, (gchar *) name); + PRINT ("};\n"); g_hash_table_iter_init (&lang_iter, all_lang_list); - g_output_stream_printf (output, NULL, NULL, &error, - "\n\nstatic const GimpLanguageDef GimpAllLanguages[GIMP_ALL_LANGS_SIZE] =" - "\n{\n"); + PRINT ("\n\nstatic const GimpLanguageDef GimpAllLanguages[GIMP_ALL_LANGS_SIZE] =\n{\n"); while (g_hash_table_iter_next (&lang_iter, &code, &name)) - g_output_stream_printf (output, NULL, NULL, &error, - " { \"%s\", \"%s\" },\n", (gchar *) code, (gchar *) name); - g_output_stream_printf (output, NULL, NULL, &error, "};\n"); + PRINT (" { \"%s\", \"%s\" },\n", (gchar *) code, (gchar *) name); + PRINT ("};\n"); gimp_language_store_parser_clean (); @@ -175,21 +184,22 @@ main (int argc, * Initialize and run the language listing parser. This call must be * made only once, at program initialization, but after language_init(). */ -static void -gimp_language_store_parser_init (void) +static gboolean +gimp_language_store_parser_init (GError **error) { GTimer *timer = g_timer_new (); GHashTable *base_lang_list; gchar *current_env; GDir *locales_dir; - GError *error = NULL; GHashTableIter lang_iter; gpointer key; + gboolean success = TRUE; if (l10n_lang_list != NULL) { - g_warning ("gimp_language_store_parser_init() must be run only once."); - return; + g_set_error_literal (error, G_IO_ERROR, 0, + "gimp_language_store_parser_init() must be run only once."); + return FALSE; } current_env = g_strdup (g_getenv ("LANGUAGE")); @@ -205,10 +215,12 @@ gimp_language_store_parser_init (void) (GDestroyNotify) g_free); /* Check all locales we have translations for. */ - locales_dir = g_dir_open (gimp_locale_directory (), 0, NULL); + locales_dir = g_dir_open (gimp_locale_directory (), 0, error); if (locales_dir) { const gchar *locale; + gint n_locales = 0; + gint n_mo = 0; while ((locale = g_dir_read_name (locales_dir)) != NULL) { @@ -242,16 +254,39 @@ gimp_language_store_parser_init (void) g_hash_table_insert (l10n_lang_list, g_strdup (locale), NULL); /* Save the base language code. */ g_hash_table_insert (base_lang_list, base_code, NULL); + + n_mo++; } + n_locales++; + g_free (filename); } g_dir_close (locales_dir); + + if (n_mo == 0) + { + g_set_error (error, G_IO_ERROR, 0, + "No \"%s\" file was found in %s in %d locales", + GETTEXT_PACKAGE ".mo", gimp_locale_directory (), + n_locales); + success = FALSE; + goto cleanup; + } + } + else + { + success = FALSE; + goto cleanup; } /* Parse ISO-639 file to get full list of language and their names. */ - parse_iso_codes (base_lang_list, &error); + if (! parse_iso_codes (base_lang_list, error)) + { + success = FALSE; + goto cleanup; + } /* Generate the localized language names. */ g_hash_table_iter_init (&lang_iter, l10n_lang_list); @@ -351,11 +386,14 @@ gimp_language_store_parser_init (void) g_hash_table_insert (l10n_lang_list, g_strdup ("en_US"), g_strdup ("English [en_US]")); +cleanup: g_hash_table_destroy (base_lang_list); g_timer_stop (timer); g_print ("%s: %f seconds\n", G_STRFUNC, g_timer_elapsed (timer, NULL)); g_timer_destroy (timer); + + return success; } static void @@ -407,12 +445,18 @@ parse_iso_codes (GHashTable *base_lang_list, "iso_639_3.xml"); success = gimp_xml_parser_parse_gfile (xml_parser, file, error); - if (error && *error) + if (*error) { - g_warning ("%s: error parsing '%s': %s\n", - G_STRFUNC, g_file_get_path (file), - (*error)->message); - g_clear_error (error); + g_prefix_error (error, "%s: error parsing '%s': ", + G_STRFUNC, g_file_peek_path (file)); + success = FALSE; + } + else if (g_hash_table_size (all_lang_list) == 0) + { + g_set_error (error, G_IO_ERROR, 0, + "No language entries found in %s.", + g_file_peek_path (file)); + success = FALSE; } g_object_unref (file);