Stop sharing requirement_unit_state_ereq().
[freeciv.git] / common / fc_cmdhelp.c
blob42fb13f1f3207bf029c1c49dd647bb0823d6ed8d
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 <stdarg.h>
20 /* utility */
21 #include "fciconv.h"
22 #include "fcintl.h"
23 #include "mem.h"
24 #include "shared.h"
25 #include "support.h"
27 /* common */
28 #include "version.h"
30 #include "fc_cmdhelp.h"
32 struct cmdarg {
33 char shortarg;
34 char *longarg;
35 char *helpstr;
38 /* 'struct cmdarg_list' and related functions. */
39 #define SPECLIST_TAG cmdarg
40 #define SPECLIST_TYPE struct cmdarg
41 #include "speclist.h"
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
46 struct cmdhelp {
47 char *cmdname;
48 struct cmdarg_list *cmdarglist;
51 static struct cmdarg *cmdarg_new(const char *shortarg, const char *longarg,
52 const char *helpstr);
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();
67 return pcmdhelp;
70 /*****************************************************************************
71 Destroy a command help struct.
72 *****************************************************************************/
73 void cmdhelp_destroy(struct cmdhelp *pcmdhelp)
75 if (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;
83 free(pcmdhelp);
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, ...)
92 va_list args;
93 char buf[512];
94 struct cmdarg *pcmdarg;
96 va_start(args, helpstr);
97 fc_vsnprintf(buf, sizeof(buf), helpstr, args);
98 va_end(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,
108 bool report_bugs)
110 fc_fprintf(stderr, _("Usage: %s [option ...]\nValid option are:\n"),
111 pcmdhelp->cmdname);
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);
118 } else {
119 fc_fprintf(stderr, " --%-15s %s\n", pcmdarg->longarg,
120 pcmdarg->helpstr);
122 } cmdarg_list_iterate_end;
124 if (gui_options) {
125 char buf[128];
127 fc_snprintf(buf, sizeof(buf), _("Try \"%s -- --help\" for more."),
128 pcmdhelp->cmdname);
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);
137 if (report_bugs) {
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,
147 const char *helpstr)
149 struct cmdarg *pcmdarg = fc_calloc(1, sizeof(*pcmdarg));
151 if (shortarg && strlen(shortarg) == 1) {
152 pcmdarg->shortarg = shortarg[0];
153 } else {
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);
160 return pcmdarg;
163 /*****************************************************************************
164 Destroy a command argument struct.
165 *****************************************************************************/
166 static void cmdarg_destroy(struct cmdarg *pcmdarg)
168 if (pcmdarg) {
169 if (pcmdarg->longarg) {
170 free(pcmdarg->longarg);
172 if (pcmdarg->helpstr) {
173 free(pcmdarg->helpstr);
176 free(pcmdarg);
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;
187 int c0, c1;
189 if (pcmdarg0 == NULL) {
190 return -1;
192 if (pcmdarg1 == NULL) {
193 return 1;
196 /* Arguments without a short option are listed at the end sorted by the
197 * long option. */
198 if (pcmdarg0->shortarg == '\0') {
199 if (pcmdarg1->shortarg == '\0') {
200 return fc_strcasecmp(pcmdarg0->longarg, pcmdarg1->longarg);
201 } else {
202 return 1;
205 if (pcmdarg1->shortarg == '\0') {
206 return -1;
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);
213 if (c0 == c1) {
214 return (int) (unsigned char)pcmdarg0->shortarg
215 - (int) (unsigned char)pcmdarg1->shortarg;
216 } else {
217 return c0 - c1;