Replaced deprecated gtk_menu_popup() calls with modern constructs in gtk3.22-client
[freeciv.git] / utility / fc_cmdline.c
blobc1b4fa0b75061973027d670f1a0ad499d24913a1
1 /***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include "fc_prehdrs.h"
20 #include <string.h>
22 /* utility */
23 #include "fciconv.h"
24 #include "fcintl.h"
25 #include "mem.h"
26 #include "support.h"
28 #include "fc_cmdline.h"
30 /* get 'struct cmdline_value_list' and related functions: */
31 #define SPECLIST_TAG cmdline_value
32 #define SPECLIST_TYPE char
33 #include "speclist.h"
35 #define cmdline_value_list_iterate(vallist, pvalue) \
36 TYPED_LIST_ITERATE(char *, vallist, pvalue)
37 #define cmdline_value_list_iterate_end LIST_ITERATE_END
39 static struct cmdline_value_list *cmdline_values = NULL;
41 /**************************************************************************
42 Return a char* to the parameter of the option or NULL.
43 *i can be increased to get next string in the array argv[].
44 It is an error for the option to exist but be an empty string.
45 This doesn't use log_*() because it is used before logging is set up.
47 The argv strings are assumed to be in the local encoding; the returned
48 string is in the internal encoding.
49 **************************************************************************/
50 char *get_option_malloc(const char *option_name,
51 char **argv, int *i, int argc,
52 bool gc)
54 int len = strlen(option_name);
56 if (gc && cmdline_values == NULL) {
57 cmdline_values = cmdline_value_list_new();
60 if (strcmp(option_name, argv[*i]) == 0
61 || (strncmp(option_name, argv[*i], len) == 0 && argv[*i][len] == '=')
62 || strncmp(option_name + 1, argv[*i], 2) == 0) {
63 char *opt = argv[*i] + (argv[*i][1] != '-' ? 0 : len);
64 char *ret;
66 if (*opt == '=') {
67 opt++;
68 } else {
69 if (*i < argc - 1) {
70 (*i)++;
71 opt = argv[*i];
72 if (strlen(opt) == 0) {
73 fc_fprintf(stderr, _("Empty argument for \"%s\".\n"), option_name);
74 exit(EXIT_FAILURE);
76 } else {
77 fc_fprintf(stderr, _("Missing argument for \"%s\".\n"), option_name);
78 exit(EXIT_FAILURE);
82 ret = local_to_internal_string_malloc(opt);
84 if (gc) {
85 cmdline_value_list_append(cmdline_values, ret);
88 return ret;
91 return NULL;
94 /***************************************************************
95 Free memory allocated for commandline option values.
96 ***************************************************************/
97 void cmdline_option_values_free(void)
99 if (cmdline_values != NULL) {
100 cmdline_value_list_iterate(cmdline_values, pval) {
101 free(pval);
102 } cmdline_value_list_iterate_end;
104 cmdline_value_list_destroy(cmdline_values);
108 /***************************************************************
109 Is option some form of option_name. option_name must be
110 full length long version such as "--help"
111 ***************************************************************/
112 bool is_option(const char *option_name,char *option)
114 return (strcmp(option_name, option) == 0
115 || strncmp(option_name + 1, option, 2) == 0);
118 /***************************************************************
119 Like strcspn but also handles quotes, i.e. *reject chars are
120 ignored if they are inside single or double quotes.
121 ***************************************************************/
122 static size_t fc_strcspn(const char *s, const char *reject)
124 bool in_single_quotes = FALSE, in_double_quotes = FALSE;
125 size_t i, len = strlen(s);
127 for (i = 0; i < len; i++) {
128 if (s[i] == '"' && !in_single_quotes) {
129 in_double_quotes = !in_double_quotes;
130 } else if (s[i] == '\'' && !in_double_quotes) {
131 in_single_quotes = !in_single_quotes;
134 if (in_single_quotes || in_double_quotes) {
135 continue;
138 if (strchr(reject, s[i])) {
139 break;
143 return i;
146 /***************************************************************
147 Splits the string into tokens. The individual tokens are
148 returned. The delimiterset can freely be chosen.
150 i.e. "34 abc 54 87" with a delimiterset of " " will yield
151 tokens={"34", "abc", "54", "87"}
153 Part of the input string can be quoted (single or double) to embedded
154 delimiter into tokens. For example,
155 command 'a name' hard "1,2,3,4,5" 99
156 create 'Mack "The Knife"'
157 will yield 5 and 2 tokens respectively using the delimiterset " ,".
159 Tokens which aren't used aren't modified (and memory is not
160 allocated). If the string would yield more tokens only the first
161 num_tokens are extracted.
163 The user has the responsiblity to free the memory allocated by
164 **tokens using free_tokens().
165 ***************************************************************/
166 int get_tokens(const char *str, char **tokens, size_t num_tokens,
167 const char *delimiterset)
169 int token = 0;
171 fc_assert_ret_val(NULL != str, -1);
173 for(;;) {
174 size_t len, padlength = 0;
176 /* skip leading delimiters */
177 str += strspn(str, delimiterset);
179 if (*str == '\0') {
180 break;
183 len = fc_strcspn(str, delimiterset);
185 if (token >= num_tokens) {
186 break;
189 /* strip start/end quotes if they exist */
190 if (len >= 2) {
191 if ((str[0] == '"' && str[len - 1] == '"')
192 || (str[0] == '\'' && str[len - 1] == '\'')) {
193 len -= 2;
194 padlength = 1; /* to set the string past the end quote */
195 str++;
199 tokens[token] = fc_malloc(len + 1);
200 (void) fc_strlcpy(tokens[token], str, len + 1); /* adds the '\0' */
202 token++;
204 str += len + padlength;
207 return token;
210 /***************************************************************
211 Frees a set of tokens created by get_tokens().
212 ***************************************************************/
213 void free_tokens(char **tokens, size_t ntokens)
215 size_t i;
217 for (i = 0; i < ntokens; i++) {
218 if (tokens[i]) {
219 free(tokens[i]);