options.c
1 /** 2 * Copyright © 2016-2022 Dr. Tobias Quathamer <toddy@debian.org> 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include <stdlib.h> 19 #include <glib.h> 20 #include <glib/gi18n.h> 21 #include <glib/gprintf.h> 22 #include "options.h" 23 24 /** 25 * Global variables to hold the program options. 26 */ 27 gchar *option_standard; 28 gchar *option_pathname; 29 gchar *option_namefield; 30 gchar *option_locale; 31 gboolean *option_null_separator; 32 gboolean *option_flag_output; 33 gboolean *option_version; 34 35 // Helper variables, not to be accessed directly. 36 gboolean *option_name; 37 gboolean *option_officialname; 38 gboolean *option_commonname; 39 40 /** 41 * Define the program command line options. 42 */ 43 static GOptionEntry entries[] = { 44 { "iso", 'i', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &option_standard, 45 N_ 46 ("The ISO standard to use. Possible values: 639-2, 639-3, 639-5, 3166-1, 3166-2, 3166-3, 4217, 15924 (default: 3166-1)"), 47 N_("STANDARD") }, 48 { "pathname", 'p', G_OPTION_FLAG_NONE, G_OPTION_ARG_FILENAME, &option_pathname, 49 N_("Use pathname as prefix for the data files (default: /usr/share/iso-codes/json)"), 50 N_("PATHNAME") }, 51 { "locale", 'l', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &option_locale, 52 N_("Use this locale for output"), 53 N_("LOCALE") }, 54 { "name", 'n', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &option_name, 55 N_("Name for the supplied codes (default)"), NULL }, 56 { "official_name", 'o', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &option_officialname, 57 N_("Official name for the supplied codes. This may be the same as --name (only applies to ISO 3166-1)"), 58 NULL }, 59 { "common_name", 'c', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &option_commonname, 60 N_ 61 ("Common name for the supplied codes. This may be the same as --name (only applies to ISO 639-2, 639-3, and 3166-1)"), 62 NULL }, 63 { "null", '0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &option_null_separator, 64 N_("Separate entries with a NULL character instead of newline"), NULL }, 65 { "flag", 'f', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &option_flag_output, 66 N_("Show country flags with regional indicator symbol letters (only applies to ISO 3166-1)"), NULL }, 67 { "version", 'v', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &option_version, 68 N_("Show program version and copyright"), NULL }, 69 { NULL } 70 }; 71 72 /** 73 * Parse the command line arguments. 74 * 75 * @param arguments Array of arguments 76 */ 77 gboolean options_parse_command_line(gchar **arguments, GError **error) 78 { 79 int argc = 0; 80 GOptionContext *context; 81 82 // Ensure that there are sensible default options. 83 options_set_default_values(); 84 85 context = g_option_context_new(_("[ISO codes]")); 86 g_option_context_add_main_entries(context, entries, GETTEXT_PACKAGE); 87 88 // Count the number of arguments supplied. 89 while (arguments[argc] != NULL) { 90 argc++; 91 } 92 // If the parsing fails, return with error. 93 if (!g_option_context_parse(context, &argc, &arguments, error)) { 94 return FALSE; 95 } 96 // Validate options 97 if (!options_validate(error)) { 98 return FALSE; 99 } 100 return TRUE; 101 } 102 103 /** 104 * Set default values for options. 105 */ 106 void options_set_default_values(void) 107 { 108 option_standard = "3166-1"; 109 option_pathname = "/usr/share/iso-codes/json"; 110 option_namefield = "name"; 111 option_locale = ""; 112 option_null_separator = FALSE; 113 option_flag_output = FALSE; 114 option_version = FALSE; 115 } 116 117 /** 118 * Validate values of options. 119 */ 120 gboolean options_validate(GError **error) 121 { 122 // Handle deprecated standards gracefully 123 if (!g_strcmp0("3166", option_standard)) { 124 option_standard = "3166-1"; 125 // Print a small warning 126 g_printerr("isoquery: The standard 3166 is deprecated, please use 3166-1 instead.\n"); 127 } 128 if (!g_strcmp0("639", option_standard)) { 129 option_standard = "639-2"; 130 // Print a small warning 131 g_printerr("isoquery: The standard 639 is deprecated, please use 639-2 instead.\n"); 132 } 133 // Check that the given standard is supported 134 int i = 0; 135 gboolean supported = FALSE; 136 gchar *supported_standards[] = { "639-2", "639-3", "639-5", "3166-1", "3166-2", "3166-3", "4217", "15924", NULL }; 137 while (supported_standards[i]) { 138 if (!g_strcmp0(supported_standards[i], option_standard)) { 139 supported = TRUE; 140 break; 141 } 142 i++; 143 } 144 if (!supported) { 145 // TRANSLATORS: The placeholder is a string like "1234-5". 146 g_set_error(error, g_quark_from_string(GETTEXT_PACKAGE), 0, _("ISO standard \"%s\" is not supported."), 147 option_standard); 148 return FALSE; 149 } 150 // Set the value for the name field 151 if (option_officialname) { 152 option_namefield = "official_name"; 153 } 154 if (option_commonname) { 155 option_namefield = "common_name"; 156 } 157 return TRUE; 158 } 159 160 /** 161 * Construct the filename for JSON data, given the pathname and ISO standard. 162 * 163 * @return gchar * Filename, has to be free'd by the caller. 164 */ 165 gchar *options_get_filename(void) 166 { 167 gchar *filename, *complete_path; 168 filename = g_strdup_printf("iso_%s.json", option_standard); 169 complete_path = g_build_filename(option_pathname, filename, NULL); 170 g_free(filename); 171 return complete_path; 172 } 173 174 /** 175 * Show program version and copyright 176 */ 177 void options_show_version(void) 178 { 179 // TRANSLATORS: The placeholder is the version identifier. 180 g_printf(_("isoquery %s\n"), VERSION); 181 g_printf(_("Copyright © 2007-2022 Dr. Tobias Quathamer\n")); 182 // TRANSLATORS: Please change the uppercase words as 183 // appropriate for your language. 184 gchar *translation = _("Translation to LANGUAGE Copyright © YEAR YOUR-NAME\n"); 185 if (!g_strrstr(translation, "LANGUAGE")) { 186 g_printf("%s", translation); 187 } 188 g_print("\n"); 189 g_print("This program is free software: you can redistribute it and/or modify\n"); 190 g_print("it under the terms of the GNU General Public License as published by\n"); 191 g_print("the Free Software Foundation, either version 3 of the License, or\n"); 192 g_print("(at your option) any later version.\n"); 193 g_print("\n"); 194 g_print("This program is distributed in the hope that it will be useful,\n"); 195 g_print("but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); 196 g_print("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); 197 g_print("GNU General Public License for more details.\n"); 198 g_print("\n"); 199 g_print("You should have received a copy of the GNU General Public License\n"); 200 g_print("along with this program. If not, see <http://www.gnu.org/licenses/>.\n"); 201 }