webperimental: killstack decides stack protects.
[freeciv.git] / tools / civmanual.c
blobde780b3aed1ae71dc38a7ad9c1c2982f5ce7d990
1 /***********************************************************************
2 Freeciv - Copyright (C) 2004 - The Freeciv Project
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 <assert.h>
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
24 #ifdef HAVE_SIGNAL_H
25 #include <signal.h>
26 #endif
28 /* utility */
29 #include "capability.h"
30 #include "fc_cmdline.h"
31 #include "fciconv.h"
32 #include "fcintl.h"
33 #include "log.h"
34 #include "mem.h"
35 #include "registry.h"
36 #include "support.h"
38 /* common */
39 #include "connection.h"
40 #include "events.h"
41 #include "fc_cmdhelp.h"
42 #include "fc_interface.h"
43 #include "fc_types.h" /* LINE_BREAK */
44 #include "game.h"
45 #include "government.h"
46 #include "improvement.h"
47 #include "map.h"
48 #include "movement.h"
49 #include "player.h"
50 #include "version.h"
52 /* client */
53 #include "client_main.h"
54 #include "climisc.h"
55 #include "helpdata.h"
56 #include "helpdlg_g.h"
57 #include "tilespec.h"
59 /* server */
60 #include "citytools.h"
61 #include "commands.h"
62 #include "connecthand.h"
63 #include "console.h"
64 #include "diplhand.h"
65 #include "gamehand.h"
66 #include "plrhand.h"
67 #include "report.h"
68 #include "ruleset.h"
69 #include "settings.h"
70 #include "sernet.h"
71 #include "srv_main.h"
72 #include "stdinhand.h"
74 /* tools/shared */
75 #include "tools_fc_interface.h"
77 enum manuals {
78 MANUAL_SETTINGS,
79 MANUAL_COMMANDS,
80 MANUAL_TERRAIN,
81 MANUAL_BUILDINGS,
82 MANUAL_WONDERS,
83 MANUAL_GOVS,
84 MANUAL_UNITS,
85 MANUAL_TECHS,
86 MANUAL_COUNT
89 /* This formats the manual for an HTML wiki. */
90 #ifdef MANUAL_USE_HTML
91 #define FILE_EXT "html"
92 #define HEADER "<html><head><link rel=\"stylesheet\" type=\"text/css\" "\
93 "href=\"manual.css\"/><meta http-equiv=\"Content-Type\" "\
94 "content=\"text/html; charset=UTF-8\"/></head><body>\n\n"
95 #define TITLE_BEGIN "<h1>"
96 #define TITLE_END "</h1>"
97 #define SECTION_TITLE_BEGIN "<h3 class='section'>"
98 #define SECTION_TITLE_END "</h3>"
99 #define IMAGE_BEGIN "<img src=\""
100 #define IMAGE_END ".png\">"
101 #define ITEM_BEGIN "<div class='item' id='%s%d'>\n"
102 #define ITEM_END "</div>\n"
103 #define SUBITEM_BEGIN "<pre class='%s'>"
104 #define SUBITEM_END "</pre>\n"
105 #define TAIL "</body></html>"
106 #else /* MANUAL_USE_HTML */
107 #define FILE_EXT "mediawiki"
108 #define HEADER " "
109 #define TITLE_BEGIN "="
110 #define TITLE_END "="
111 #define SECTION_TITLE_BEGIN "==="
112 #define SECTION_TITLE_END "==="
113 #define IMAGE_BEGIN "[[Image:"
114 #define IMAGE_END ".png]]"
115 #define ITEM_BEGIN "----\n<!-- %s %d -->\n"
116 #define ITEM_END "\n"
117 #define SUBITEM_BEGIN "<!-- %s -->\n"
118 #define SUBITEM_END "\n"
119 #define TAIL " "
120 #endif /* MANUAL_USE_HTML */
122 void insert_client_build_info(char *outbuf, size_t outlen);
124 /* Needed for "About Freeciv" help */
125 const char *client_string = "freeciv-manual";
127 static char *ruleset = NULL;
129 /**************************************************************************
130 Replace html special characters ('&', '<' and '>').
131 **************************************************************************/
132 static char *html_special_chars(char *str, size_t *len)
134 char *buf;
136 buf = fc_strrep_resize(str, len, "&", "&amp;");
137 buf = fc_strrep_resize(buf, len, "<", "&lt;");
138 buf = fc_strrep_resize(buf, len, ">", "&gt;");
140 return buf;
144 /*******************************************
145 Useless stubs for compiling client code.
148 /**************************************************************************
149 Client stub
150 **************************************************************************/
151 void popup_help_dialog_string(const char *item)
153 /* Empty stub. */
156 /**************************************************************************
157 Client stub
158 **************************************************************************/
159 void popdown_help_dialog(void)
161 /* Empty stub. */
164 struct tileset *tileset;
166 /**************************************************************************
167 Client stub
168 **************************************************************************/
169 const char *tileset_name_get(struct tileset *t)
171 return NULL;
174 /**************************************************************************
175 Client stub
176 **************************************************************************/
177 const char *tileset_version(struct tileset *t)
179 return NULL;
182 /**************************************************************************
183 Client stub
184 **************************************************************************/
185 const char *tileset_summary(struct tileset *t)
187 return NULL;
190 /**************************************************************************
191 Client stub
192 **************************************************************************/
193 const char *tileset_description(struct tileset *t)
195 return NULL;
198 enum client_states client_state(void)
200 return C_S_INITIAL;
203 bool client_nation_is_in_current_set(const struct nation_type *pnation)
205 /* Currently, there is no way to select a nation set for freeciv-manual.
206 * Then, let's assume we want to print help for all nations. */
207 return TRUE;
210 /**************************************************************************
211 Write a server manual in the format chosen at build time, then quit.
212 **************************************************************************/
213 static bool manual_command(void)
215 FILE *doc;
216 char filename[40];
217 enum manuals manuals;
218 struct connection my_conn;
220 /* Default client access. */
221 connection_common_init(&my_conn);
222 my_conn.access_level = ALLOW_CTRL;
224 /* Reset aifill to zero */
225 game.info.aifill = 0;
227 if (!load_rulesets(NULL, FALSE, FALSE, FALSE)) {
228 /* Failed to load correct ruleset */
229 return FALSE;
232 for (manuals = 0; manuals < MANUAL_COUNT; manuals++) {
233 int i;
234 int ri;
236 fc_snprintf(filename, sizeof(filename), "%s%d.%s",
237 game.server.rulesetdir, manuals + 1, FILE_EXT);
239 if (!is_reg_file_for_access(filename, TRUE)
240 || !(doc = fc_fopen(filename, "w"))) {
241 log_error(_("Could not write manual file %s."), filename);
242 return FALSE;
245 fprintf(doc, HEADER);
246 fprintf(doc, "<!-- Generated by freeciv-manual version %s -->\n\n",
247 freeciv_datafile_version());
249 switch (manuals) {
250 case MANUAL_SETTINGS:
251 /* TRANS: markup ... Freeciv version ... ruleset name ... markup */
252 fprintf(doc, _("%sFreeciv %s server options (%s)%s\n\n"), TITLE_BEGIN,
253 VERSION_STRING, game.control.name, TITLE_END);
254 settings_iterate(SSET_ALL, pset) {
255 char buf[256];
256 const char *sethelp;
258 fprintf(doc, ITEM_BEGIN, "setting", setting_number(pset));
259 fprintf(doc, "%s%s - %s%s\n\n", SECTION_TITLE_BEGIN,
260 setting_name(pset), _(setting_short_help(pset)),
261 SECTION_TITLE_END);
262 sethelp = _(setting_extra_help(pset, TRUE));
263 if (strlen(sethelp) > 0) {
264 char *help = fc_strdup(sethelp);
265 size_t help_len = strlen(help) + 1;
267 fc_break_lines(help, LINE_BREAK);
268 help = html_special_chars(help, &help_len);
269 fprintf(doc, "<pre>%s</pre>\n\n", help);
270 FC_FREE(help);
272 fprintf(doc, "<p class=\"misc\">");
273 fprintf(doc, _("Level: %s.<br>"),
274 _(sset_level_name(setting_level(pset))));
275 fprintf(doc, _("Category: %s.<br>"),
276 _(sset_category_name(setting_category(pset))));
278 /* first check if the setting is locked because this is included in
279 * the function setting_is_changeable() */
280 if (setting_locked(pset)) {
281 fprintf(doc, _("Is locked by the ruleset."));
282 } else if (!setting_is_changeable(pset, &my_conn, NULL, 0)) {
283 fprintf(doc, _("Can only be used in server console."));
286 fprintf(doc, "</p>\n");
287 setting_default_name(pset, TRUE, buf, sizeof(buf));
288 switch (setting_type(pset)) {
289 case SST_INT:
290 fprintf(doc, "\n<p class=\"bounds\">%s %d, %s %s, %s %d</p>\n",
291 _("Minimum:"), setting_int_min(pset),
292 _("Default:"), buf,
293 _("Maximum:"), setting_int_max(pset));
294 break;
295 case SST_ENUM:
297 const char *value;
299 fprintf(doc, "\n<p class=\"bounds\">%s</p>",
300 _("Possible values:"));
301 for (i = 0; (value = setting_enum_val(pset, i, FALSE)); i++) {
302 fprintf(doc, "\n<p class=\"bounds\"><li/> %s: \"%s\"</p>",
303 value, setting_enum_val(pset, i, TRUE));
306 break;
307 case SST_BITWISE:
309 const char *value;
311 fprintf(doc, "\n<p class=\"bounds\">%s</p>",
312 _("Possible values (option can take any number of these):"));
313 for (i = 0; (value = setting_bitwise_bit(pset, i, FALSE)); i++) {
314 fprintf(doc, "\n<p class=\"bounds\"><li/> %s: \"%s\"</p>",
315 value, setting_bitwise_bit(pset, i, TRUE));
318 break;
319 case SST_BOOL:
320 case SST_STRING:
321 break;
322 case SST_COUNT:
323 fc_assert(setting_type(pset) != SST_COUNT);
324 break;
326 if (SST_INT != setting_type(pset)) {
327 fprintf(doc, "\n<p class=\"bounds\">%s %s</p>\n",
328 _("Default:"), buf);
330 if (setting_non_default(pset)) {
331 fprintf(doc, _("\n<p class=\"changed\">Value set to %s</p>\n"),
332 setting_value_name(pset, TRUE, buf, sizeof(buf)));
335 fprintf(doc, ITEM_END);
336 } settings_iterate_end;
337 break;
339 case MANUAL_COMMANDS:
340 /* TRANS: markup ... Freeciv version ... markup */
341 fprintf(doc, _("%sFreeciv %s server commands%s\n\n"), TITLE_BEGIN,
342 VERSION_STRING, TITLE_END);
343 for (i = 0; i < CMD_NUM; i++) {
344 const struct command *cmd = command_by_number(i);
346 fprintf(doc, ITEM_BEGIN, "cmd", i);
347 fprintf(doc, "%s%s - %s%s\n\n", SECTION_TITLE_BEGIN,
348 command_name(cmd), command_short_help(cmd),
349 SECTION_TITLE_END);
350 if (command_synopsis(cmd)) {
351 char *cmdstr = fc_strdup(command_synopsis(cmd));
352 size_t cmdstr_len = strlen(cmdstr) + 1;
354 cmdstr = html_special_chars(cmdstr, &cmdstr_len);
355 fprintf(doc, _("<table>\n<tr>\n<td valign=\"top\">"
356 "<pre>Synopsis:</pre></td>\n<td>"));
357 fprintf(doc, "<pre>%s</pre></td></tr></table>", cmdstr);
358 FC_FREE(cmdstr);
360 fprintf(doc, _("<p class=\"level\">Level: %s</p>\n"),
361 cmdlevel_name(command_level(cmd)));
363 char *help = command_extra_help(cmd);
364 if (help) {
365 size_t help_len = strlen(help) + 1;
367 fc_break_lines(help, LINE_BREAK);
368 help = html_special_chars(help, &help_len);
369 fprintf(doc, "\n");
370 fprintf(doc, _("<p>Description:</p>\n\n"));
371 fprintf(doc, "<pre>%s</pre>\n", help);
372 FC_FREE(help);
376 fprintf(doc, ITEM_END);
378 break;
380 case MANUAL_TERRAIN:
381 /* TRANS: markup ... Freeciv version ... ruleset name ... markup */
382 fprintf(doc, _("%sFreeciv %s terrain help (%s)%s\n\n"), TITLE_BEGIN,
383 VERSION_STRING, game.control.name, TITLE_END);
384 fprintf(doc, "<table><tr bgcolor=#9bc3d1><th colspan=2>%s</th>", _("Terrain"));
385 fprintf(doc, "<th>F/P/T</th><th>%s</th>", _("Resources"));
386 fprintf(doc, "<th>%s<br/>%s</th>", _("Move cost"), _("Defense bonus"));
387 fprintf(doc, "<th>%s<br/>%s<br/>%s<br/>%s<br/>(%s)</th>",
388 _("Irrigation"), _("Mining"), _("Transform"),
389 /* xgettext:no-c-format */
390 _("% of Road bonus"), _("turns"));
391 fprintf(doc, "<th>%s<br/>%s</th>",
392 _("Clean pollution"), _("Clean fallout"));
393 ri = 0;
394 if (game.control.num_road_types > 0) {
395 fprintf(doc, "<th>");
397 extra_type_by_cause_iterate(EC_ROAD, pextra) {
398 if (++ri < game.control.num_road_types) {
399 fprintf(doc, "%s<br/>", extra_name_translation(pextra));
400 } else {
401 /* Last one */
402 fprintf(doc, "%s</th>", extra_name_translation(pextra));
404 } extra_type_by_cause_iterate_end;
405 fprintf(doc, "</tr>\n\n");
406 terrain_type_iterate(pterrain) {
407 struct extra_type **r;
409 if (0 == strlen(terrain_rule_name(pterrain))) {
410 /* Must be a disabled piece of terrain */
411 continue;
414 fprintf(doc, "<tr><td>" IMAGE_BEGIN "%s" IMAGE_END "</td><td>%s</td>",
415 pterrain->graphic_str, terrain_name_translation(pterrain));
416 fprintf(doc, "<td>%d/%d/%d</td>\n",
417 pterrain->output[O_FOOD], pterrain->output[O_SHIELD],
418 pterrain->output[O_TRADE]);
420 fprintf(doc, "<td><table width=\"100%%\">\n");
421 for (r = pterrain->resources; *r; r++) {
422 fprintf(doc, "<tr><td>" IMAGE_BEGIN "%s" IMAGE_END "</td><td>%s</td>"
423 "<td align=\"right\">%d/%d/%d</td></tr>\n",
424 (*r)->graphic_str,
425 extra_name_translation(*r),
426 (*r)->data.resource->output[O_FOOD],
427 (*r)->data.resource->output[O_SHIELD],
428 (*r)->data.resource->output[O_TRADE]);
430 fprintf(doc, "</table></td>\n");
432 fprintf(doc, "<td align=\"center\">%d<br/>+%d%%</td>\n",
433 pterrain->movement_cost, pterrain->defense_bonus);
435 fprintf(doc, "<td><table width=\"100%%\">\n");
436 if (pterrain->irrigation_result == pterrain) {
437 fprintf(doc, "<tr><td>+%d F</td><td align=\"right\">(%d)</td></tr>\n",
438 pterrain->irrigation_food_incr, pterrain->irrigation_time);
439 } else if (pterrain->irrigation_result == T_NONE) {
440 fprintf(doc, "<tr><td>%s</td></tr>\n", _("impossible"));
441 } else {
442 fprintf(doc, "<tr><td>%s</td><td align=\"right\">(%d)</td></tr>\n",
443 terrain_name_translation(pterrain->irrigation_result),
444 pterrain->irrigation_time);
446 if (pterrain->mining_result == pterrain) {
447 fprintf(doc, "<tr><td>+%d P</td><td align=\"right\">(%d)</td></tr>\n",
448 pterrain->mining_shield_incr, pterrain->mining_time);
449 } else if (pterrain->mining_result == T_NONE) {
450 fprintf(doc, "<tr><td>%s</td></tr>\n", _("impossible"));
451 } else {
452 fprintf(doc, "<tr><td>%s</td><td align=\"right\">(%d)</td></tr>\n",
453 terrain_name_translation(pterrain->mining_result),
454 pterrain->mining_time);
457 if (pterrain->transform_result) {
458 fprintf(doc, "<tr><td>%s</td><td align=\"right\">(%d)</td></tr>\n",
459 terrain_name_translation(pterrain->transform_result),
460 pterrain->transform_time);
461 } else {
462 fprintf(doc, "<tr><td>-</td><td align=\"right\">(-)</td></tr>\n");
464 fprintf(doc, "<tr><td>%d / %d / %d</td></tr>\n</table></td>\n",
465 pterrain->road_output_incr_pct[O_FOOD],
466 pterrain->road_output_incr_pct[O_SHIELD],
467 pterrain->road_output_incr_pct[O_TRADE]);
469 fprintf(doc, "<td align=\"center\">%d / %d</td>",
470 pterrain->clean_pollution_time, pterrain->clean_fallout_time);
472 ri = 0;
473 if (game.control.num_road_types > 0) {
474 fprintf(doc, "<td>");
476 extra_type_by_cause_iterate(EC_ROAD, pextra) {
477 if (++ri < game.control.num_road_types) {
478 fprintf(doc, "%d / ", terrain_extra_build_time(pterrain, ACTIVITY_GEN_ROAD,
479 pextra));
480 } else {
481 fprintf(doc, "%d</td>", terrain_extra_build_time(pterrain, ACTIVITY_GEN_ROAD,
482 pextra));
484 } extra_type_by_cause_iterate_end;
485 fprintf(doc, "</tr>\n\n");
486 } terrain_type_iterate_end;
488 fprintf(doc, "</table>\n");
490 break;
492 case MANUAL_BUILDINGS:
493 case MANUAL_WONDERS:
494 if (manuals == MANUAL_BUILDINGS) {
495 /* TRANS: markup ... Freeciv version ... ruleset name ... markup */
496 fprintf(doc, _("%sFreeciv %s buildings help (%s)%s\n\n"), TITLE_BEGIN,
497 VERSION_STRING, game.control.name, TITLE_END);
498 } else {
499 /* TRANS: markup ... Freeciv version ... ruleset name ... markup */
500 fprintf(doc, _("%sFreeciv %s wonders help (%s)%s\n\n"), TITLE_BEGIN,
501 VERSION_STRING, game.control.name, TITLE_END);
504 fprintf(doc, "<table>\n<tr bgcolor=#9bc3d1><th colspan=2>%s</th>"
505 "<th>%s<br/>%s</th><th>%s<br/>%s</th><th>%s</th></tr>\n\n",
506 _("Name"), _("Cost"), _("Upkeep"),
507 _("Requirement"), _("Obsolete by"), _("More info"));
509 improvement_iterate(pimprove) {
510 char buf[64000];
511 struct advance *obs_tech = NULL;
513 if (!valid_improvement(pimprove)
514 || is_great_wonder(pimprove) == (manuals == MANUAL_BUILDINGS)) {
515 continue;
518 helptext_building(buf, sizeof(buf), NULL, NULL, pimprove);
520 fprintf(doc, "<tr><td>" IMAGE_BEGIN "%s" IMAGE_END "</td><td>%s</td>\n"
521 "<td align=\"center\"><b>%d</b><br/>%d</td>\n<td>",
522 pimprove->graphic_str,
523 improvement_name_translation(pimprove),
524 pimprove->build_cost,
525 pimprove->upkeep);
527 requirement_vector_iterate(&pimprove->reqs, req) {
528 char text[512], text2[512];
529 fc_snprintf(text2, sizeof(text2),
530 /* TRANS: improvement requires a feature to be absent. */
531 req->present ? "%s" : _("no %s"),
532 VUT_NONE != req->source.kind
533 ? universal_name_translation(&req->source,
534 text, sizeof(text))
535 : Q_("?req:None"));
536 fprintf(doc, "%s<br/>", text2);
537 } requirement_vector_iterate_end;
539 requirement_vector_iterate(&pimprove->obsolete_by, pobs) {
540 if (pobs->source.kind == VUT_ADVANCE) {
541 obs_tech = pobs->source.value.advance;
542 break;
544 } requirement_vector_iterate_end;
546 fprintf(doc, "<em>%s</em></td>\n",
547 obs_tech != NULL
548 ? advance_name_translation(obs_tech)
549 : Q_("?tech:None"));
550 fprintf(doc, "<td>%s</td>\n</tr>\n\n", buf);
551 } improvement_iterate_end;
552 fprintf(doc, "</table>");
553 break;
555 case MANUAL_GOVS:
556 /* Freeciv-web uses (parts of) the government HTML output in its own
557 * manual pages. */
558 /* FIXME: this doesn't resemble the wiki manual at all. */
559 /* TRANS: markup ... Freeciv version ... ruleset name ... markup */
560 fprintf(doc, _("%sFreeciv %s governments help (%s)%s\n\n"), TITLE_BEGIN,
561 VERSION_STRING, game.control.name, TITLE_END);
562 governments_iterate(pgov) {
563 char buf[64000];
564 fprintf(doc, ITEM_BEGIN, "gov", pgov->item_number);
565 fprintf(doc, "%s%s%s\n\n", SECTION_TITLE_BEGIN,
566 government_name_translation(pgov), SECTION_TITLE_END);
567 fprintf(doc, SUBITEM_BEGIN, "helptext");
568 helptext_government(buf, sizeof(buf), NULL, NULL, pgov);
569 fprintf(doc, "%s\n\n", buf);
570 fprintf(doc, SUBITEM_END);
571 fprintf(doc, ITEM_END);
572 } governments_iterate_end;
573 break;
575 case MANUAL_UNITS:
576 /* Freeciv-web uses (parts of) the unit type HTML output in its own
577 * manual pages. */
578 /* FIXME: this doesn't resemble the wiki manual at all. */
579 /* TRANS: markup ... Freeciv version ... ruleset name ... markup */
580 fprintf(doc, _("%sFreeciv %s unit types help (%s)%s\n\n"),
581 TITLE_BEGIN, VERSION_STRING, game.control.name, TITLE_END);
582 unit_type_iterate(putype) {
583 char buf[64000];
585 fprintf(doc, ITEM_BEGIN, "utype", putype->item_number);
586 fprintf(doc, "%s%s%s\n\n", SECTION_TITLE_BEGIN,
587 utype_name_translation(putype), SECTION_TITLE_END);
588 fprintf(doc, SUBITEM_BEGIN, "cost");
589 fprintf(doc,
590 PL_("Cost: %d shield",
591 "Cost: %d shields",
592 utype_build_shield_cost(putype)),
593 utype_build_shield_cost(putype));
594 fprintf(doc, SUBITEM_END);
595 fprintf(doc, SUBITEM_BEGIN, "upkeep");
596 fprintf(doc, _("Upkeep: %s"),
597 helptext_unit_upkeep_str(putype));
598 fprintf(doc, SUBITEM_END);
599 fprintf(doc, SUBITEM_BEGIN, "moves");
600 fprintf(doc, _("Moves: %s"),
601 move_points_text(putype->move_rate, TRUE));
602 fprintf(doc, SUBITEM_END);
603 fprintf(doc, SUBITEM_BEGIN, "vision");
604 fprintf(doc, _("Vision: %d"),
605 (int)sqrt((double)putype->vision_radius_sq));
606 fprintf(doc, SUBITEM_END);
607 fprintf(doc, SUBITEM_BEGIN, "attack");
608 fprintf(doc, _("Attack: %d"),
609 putype->attack_strength);
610 fprintf(doc, SUBITEM_END);
611 fprintf(doc, SUBITEM_BEGIN, "defense");
612 fprintf(doc, _("Defense: %d"),
613 putype->defense_strength);
614 fprintf(doc, SUBITEM_END);
615 fprintf(doc, SUBITEM_BEGIN, "firepower");
616 fprintf(doc, _("Firepower: %d"),
617 putype->firepower);
618 fprintf(doc, SUBITEM_END);
619 fprintf(doc, SUBITEM_BEGIN, "hitpoints");
620 fprintf(doc, _("Hitpoints: %d"),
621 putype->hp);
622 fprintf(doc, SUBITEM_END);
623 fprintf(doc, SUBITEM_BEGIN, "obsolete");
624 fprintf(doc, _("Obsolete by: %s"),
625 U_NOT_OBSOLETED == putype->obsoleted_by ?
626 Q_("?utype:None") :
627 utype_name_translation(putype->obsoleted_by));
628 fprintf(doc, SUBITEM_END);
629 fprintf(doc, SUBITEM_BEGIN, "helptext");
630 helptext_unit(buf, sizeof(buf), NULL, "", putype);
631 fprintf(doc, "%s", buf);
632 fprintf(doc, SUBITEM_END);
633 fprintf(doc, ITEM_END);
634 } unit_type_iterate_end;
635 break;
637 case MANUAL_TECHS:
638 /* FIXME: this doesn't resemble the wiki manual at all. */
639 /* TRANS: markup ... Freeciv version ... ruleset name ... markup */
640 fprintf(doc, _("%sFreeciv %s tech help (%s)%s\n\n"),
641 TITLE_BEGIN, VERSION_STRING, game.control.name, TITLE_END);
642 advance_iterate(A_FIRST, ptech) {
643 if (valid_advance(ptech)) {
644 char buf[64000];
646 fprintf(doc, ITEM_BEGIN, "tech", ptech->item_number);
647 fprintf(doc, "%s%s%s\n\n", SECTION_TITLE_BEGIN,
648 advance_name_translation(ptech), SECTION_TITLE_END);
650 fprintf(doc, SUBITEM_BEGIN, "helptext");
651 helptext_advance(buf, sizeof(buf), NULL, "", ptech->item_number);
652 fprintf(doc, "%s", buf);
653 fprintf(doc, SUBITEM_END);
655 fprintf(doc, ITEM_END);
657 } advance_iterate_end;
658 break;
660 case MANUAL_COUNT:
661 break;
663 } /* switch */
665 fprintf(doc, TAIL);
666 fclose(doc);
667 log_normal(_("Manual file %s successfully written."), filename);
668 } /* manuals */
670 return TRUE;
673 /**************************************************************************
674 Entry point of whole freeciv-manual program
675 **************************************************************************/
676 int main(int argc, char **argv)
678 int inx;
679 bool showhelp = FALSE;
680 bool showvers = FALSE;
681 char *option = NULL;
682 int retval = EXIT_SUCCESS;
684 init_nls();
685 registry_module_init();
686 init_character_encodings(FC_DEFAULT_DATA_ENCODING, FALSE);
688 /* Set the default log level. */
689 srvarg.loglevel = LOG_NORMAL;
691 /* parse command-line arguments... */
692 inx = 1;
693 while (inx < argc) {
694 if ((option = get_option_malloc("--ruleset", argv, &inx, argc, TRUE))) {
695 if (ruleset != NULL) {
696 fc_fprintf(stderr, _("Multiple rulesets requested. Only one "
697 "ruleset at a time is supported.\n"));
698 } else {
699 ruleset = option;
701 } else if (is_option("--help", argv[inx])) {
702 showhelp = TRUE;
703 break;
704 } else if (is_option("--version", argv[inx])) {
705 showvers = TRUE;
706 } else if ((option = get_option_malloc("--log", argv, &inx, argc, TRUE))) {
707 srvarg.log_filename = option;
708 #ifndef FREECIV_NDEBUG
709 } else if (is_option("--Fatal", argv[inx])) {
710 if (inx + 1 >= argc || '-' == argv[inx + 1][0]) {
711 srvarg.fatal_assertions = SIGABRT;
712 } else if (str_to_int(argv[inx + 1], &srvarg.fatal_assertions)) {
713 inx++;
714 } else {
715 fc_fprintf(stderr, _("Invalid signal number \"%s\".\n"),
716 argv[inx + 1]);
717 inx++;
718 showhelp = TRUE;
720 #endif /* FREECIV_NDEBUG */
721 } else if ((option = get_option_malloc("--debug", argv, &inx, argc, FALSE))) {
722 if (!log_parse_level_str(option, &srvarg.loglevel)) {
723 showhelp = TRUE;
724 break;
726 free(option);
727 } else {
728 fc_fprintf(stderr, _("Unrecognized option: \"%s\"\n"), argv[inx]);
729 exit(EXIT_FAILURE);
731 inx++;
734 /* must be before con_log_init() */
735 init_connections();
736 con_log_init(srvarg.log_filename, srvarg.loglevel,
737 srvarg.fatal_assertions);
738 /* logging available after this point */
740 /* Get common code to treat us as a tool. */
741 i_am_tool();
743 /* Initialize the fc_interface functions needed to generate the help
744 * text. */
745 fc_interface_init_tool();
747 /* Initialize game with default values */
748 game_init(FALSE);
750 /* Set ruleset user requested in to use */
751 if (ruleset != NULL) {
752 sz_strlcpy(game.server.rulesetdir, ruleset);
755 settings_init(FALSE);
757 if (showvers && !showhelp) {
758 fc_fprintf(stderr, "%s \n", freeciv_name_version());
759 exit(EXIT_SUCCESS);
760 } else if (showhelp) {
761 struct cmdhelp *help = cmdhelp_new(argv[0]);
763 #ifdef FREECIV_DEBUG
764 cmdhelp_add(help, "d",
765 /* TRANS: "debug" is exactly what user must type, do not translate. */
766 _("debug NUM"),
767 _("Set debug log level (%d to %d, or %d:file1,min,max:...)"),
768 LOG_FATAL, LOG_DEBUG, LOG_DEBUG);
769 #else /* FREECIV_DEBUG */
770 cmdhelp_add(help, "d",
771 /* TRANS: "debug" is exactly what user must type, do not translate. */
772 _("debug NUM"),
773 _("Set debug log level (%d to %d)"),
774 LOG_FATAL, LOG_VERBOSE);
775 #endif /* FREECIV_DEBUG */
776 #ifndef FREECIV_NDEBUG
777 cmdhelp_add(help, "F",
778 /* TRANS: "Fatal" is exactly what user must type, do not translate. */
779 _("Fatal [SIGNAL]"),
780 _("Raise a signal on failed assertion"));
781 #endif /* FREECIV_NDEBUG */
782 cmdhelp_add(help, "h", "help",
783 _("Print a summary of the options"));
784 cmdhelp_add(help, "l",
785 /* TRANS: "log" is exactly what user must type, do not translate. */
786 _("log FILE"),
787 _("Use FILE as logfile"));
788 cmdhelp_add(help, "r",
789 /* TRANS: "ruleset" is exactly what user must type, do not translate. */
790 _("ruleset RULESET"),
791 _("Make manual for RULESET"));
792 cmdhelp_add(help, "v", "version",
793 _("Print the version number"));
795 /* The function below prints a header and footer for the options.
796 * Furthermore, the options are sorted. */
797 cmdhelp_display(help, TRUE, FALSE, TRUE);
798 cmdhelp_destroy(help);
800 exit(EXIT_SUCCESS);
803 if (!manual_command()) {
804 retval = EXIT_FAILURE;
807 con_log_close();
808 registry_module_close();
809 free_libfreeciv();
810 free_nls();
811 cmdline_option_values_free();
813 return retval;
816 /**************************************************************************
817 Empty function required by helpdata
818 **************************************************************************/
819 void insert_client_build_info(char *outbuf, size_t outlen)
821 /* Nothing here */