/ src / options.c
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  }