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)
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 *****************************************************************************/
15 #include <fc_config.h>
30 #include "fc_cmdhelp.h"
38 /* 'struct cmdarg_list' and related functions. */
39 #define SPECLIST_TAG cmdarg
40 #define SPECLIST_TYPE struct cmdarg
42 #define cmdarg_list_iterate(cmdarg_list, pcmdarg) \
43 TYPED_LIST_ITERATE(struct cmdarg, cmdarg_list, pcmdarg)
44 #define cmdarg_list_iterate_end LIST_ITERATE_END
48 struct cmdarg_list
*cmdarglist
;
51 static struct cmdarg
*cmdarg_new(const char *shortarg
, const char *longarg
,
53 static void cmdarg_destroy(struct cmdarg
*pcmdarg
);
54 static int cmdarg_compare(const struct cmdarg
*const *pcmdarg0
,
55 const struct cmdarg
*const *pcmdarg1
);
57 /*****************************************************************************
58 Create a new command help struct.
59 *****************************************************************************/
60 struct cmdhelp
*cmdhelp_new(const char *cmdname
)
62 struct cmdhelp
*pcmdhelp
= fc_calloc(1, sizeof(*pcmdhelp
));
64 pcmdhelp
->cmdname
= fc_strdup(fc_basename(cmdname
));
65 pcmdhelp
->cmdarglist
= cmdarg_list_new();
70 /*****************************************************************************
71 Destroy a command help struct.
72 *****************************************************************************/
73 void cmdhelp_destroy(struct cmdhelp
*pcmdhelp
)
76 if (pcmdhelp
->cmdname
) {
77 free(pcmdhelp
->cmdname
);
79 cmdarg_list_iterate(pcmdhelp
->cmdarglist
, pcmdarg
) {
80 cmdarg_destroy(pcmdarg
);
81 } cmdarg_list_iterate_end
;
86 /*****************************************************************************
87 Add a command help moption.
88 *****************************************************************************/
89 void cmdhelp_add(struct cmdhelp
*pcmdhelp
, const char *shortarg
,
90 const char *longarg
, const char *helpstr
, ...)
94 struct cmdarg
*pcmdarg
;
96 va_start(args
, helpstr
);
97 fc_vsnprintf(buf
, sizeof(buf
), helpstr
, args
);
100 pcmdarg
= cmdarg_new(shortarg
, longarg
, buf
);
101 cmdarg_list_append(pcmdhelp
->cmdarglist
, pcmdarg
);
104 /*****************************************************************************
105 Display the help for the command.
106 *****************************************************************************/
107 void cmdhelp_display(struct cmdhelp
*pcmdhelp
, bool sort
, bool gui_options
,
110 fc_fprintf(stderr
, _("Usage: %s [option ...]\nValid option are:\n"),
113 cmdarg_list_sort(pcmdhelp
->cmdarglist
, cmdarg_compare
);
114 cmdarg_list_iterate(pcmdhelp
->cmdarglist
, pcmdarg
) {
115 if (pcmdarg
->shortarg
!= '\0') {
116 fc_fprintf(stderr
, " -%c, --%-15s %s\n", pcmdarg
->shortarg
,
117 pcmdarg
->longarg
, pcmdarg
->helpstr
);
119 fc_fprintf(stderr
, " --%-15s %s\n", pcmdarg
->longarg
,
122 } cmdarg_list_iterate_end
;
127 fc_snprintf(buf
, sizeof(buf
), _("Try \"%s -- --help\" for more."),
130 /* The nearly empty strings in the two functions below have to be adapted
131 * if the format of the command argument list above is changed.*/
132 fc_fprintf(stderr
, " -- %s\n",
133 _("Pass any following options to the UI."));
134 fc_fprintf(stderr
, " %s\n", buf
);
138 /* TRANS: No full stop after the URL, could cause confusion. */
139 fc_fprintf(stderr
, _("Report bugs at %s\n"), BUG_URL
);
143 /*****************************************************************************
144 Create a new command argument struct.
145 *****************************************************************************/
146 static struct cmdarg
*cmdarg_new(const char *shortarg
, const char *longarg
,
149 struct cmdarg
*pcmdarg
= fc_calloc(1, sizeof(*pcmdarg
));
151 if (shortarg
&& strlen(shortarg
) == 1) {
152 pcmdarg
->shortarg
= shortarg
[0];
154 /* '\0' means no short argument for this option. */
155 pcmdarg
->shortarg
= '\0';
157 pcmdarg
->longarg
= fc_strdup(longarg
);
158 pcmdarg
->helpstr
= fc_strdup(helpstr
);
163 /*****************************************************************************
164 Destroy a command argument struct.
165 *****************************************************************************/
166 static void cmdarg_destroy(struct cmdarg
*pcmdarg
)
169 if (pcmdarg
->longarg
) {
170 free(pcmdarg
->longarg
);
172 if (pcmdarg
->helpstr
) {
173 free(pcmdarg
->helpstr
);
179 /*****************************************************************************
180 Compare two command argument definitions.
181 *****************************************************************************/
182 static int cmdarg_compare(const struct cmdarg
*const *pp0
,
183 const struct cmdarg
*const *pp1
)
185 const struct cmdarg
*pcmdarg0
= *pp0
;
186 const struct cmdarg
*pcmdarg1
= *pp1
;
189 if (pcmdarg0
== NULL
) {
192 if (pcmdarg1
== NULL
) {
196 /* Arguments without a short option are listed at the end sorted by the
198 if (pcmdarg0
->shortarg
== '\0') {
199 if (pcmdarg1
->shortarg
== '\0') {
200 return fc_strcasecmp(pcmdarg0
->longarg
, pcmdarg1
->longarg
);
205 if (pcmdarg1
->shortarg
== '\0') {
209 /* All other are sorted alphabetically by the shortarg in the following
210 * order: AaBbCcDd... */
211 c0
= (int) (unsigned char) fc_tolower(pcmdarg0
->shortarg
);
212 c1
= (int) (unsigned char) fc_tolower(pcmdarg1
->shortarg
);
214 return (int) (unsigned char)pcmdarg0
->shortarg
215 - (int) (unsigned char)pcmdarg1
->shortarg
;