webperimental: killstack decides stack protects.
[freeciv.git] / server / rscompat.c
blob03b2844d649de18b2c96f9e74dcc7d9f81ffe6eb
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 /* ANSI */
19 #ifdef HAVE_STRING_H
20 #include <string.h>
21 #endif
23 /* utility */
24 #include "capability.h"
25 #include "log.h"
26 #include "registry.h"
28 /* common */
29 #include "actions.h"
30 #include "effects.h"
31 #include "game.h"
32 #include "requirements.h"
33 #include "unittype.h"
35 /* server */
36 #include "rssanity.h"
37 #include "ruleset.h"
39 #include "rscompat.h"
41 /**************************************************************************
42 Initialize rscompat information structure
43 **************************************************************************/
44 void rscompat_init_info(struct rscompat_info *info)
46 memset(info, 0, sizeof(*info));
49 /**************************************************************************
50 Ruleset files should have a capabilities string datafile.options
51 This checks the string and that the required capabilities are satisified.
52 **************************************************************************/
53 int rscompat_check_capabilities(struct section_file *file,
54 const char *filename,
55 struct rscompat_info *info)
57 const char *datafile_options;
58 bool ok = FALSE;
60 if (!(datafile_options = secfile_lookup_str(file, "datafile.options"))) {
61 log_fatal("\"%s\": ruleset capability problem:", filename);
62 ruleset_error(LOG_ERROR, "%s", secfile_error());
64 return 0;
67 if (info->compat_mode) {
68 /* Check alternative capstr first, so that when we do the main capstr check,
69 * we already know that failures there are fatal (error message correct, can return
70 * immediately) */
72 if (has_capabilities(RULESET_COMPAT_CAP, datafile_options)
73 && has_capabilities(datafile_options, RULESET_COMPAT_CAP)) {
74 ok = TRUE;
78 if (!ok) {
79 if (!has_capabilities(RULESET_CAPABILITIES, datafile_options)) {
80 log_fatal("\"%s\": ruleset datafile appears incompatible:", filename);
81 log_fatal(" datafile options: %s", datafile_options);
82 log_fatal(" supported options: %s", RULESET_CAPABILITIES);
83 ruleset_error(LOG_ERROR, "Capability problem");
85 return 0;
87 if (!has_capabilities(datafile_options, RULESET_CAPABILITIES)) {
88 log_fatal("\"%s\": ruleset datafile claims required option(s)"
89 " that we don't support:", filename);
90 log_fatal(" datafile options: %s", datafile_options);
91 log_fatal(" supported options: %s", RULESET_CAPABILITIES);
92 ruleset_error(LOG_ERROR, "Capability problem");
94 return 0;
98 return secfile_lookup_int_default(file, 1, "datafile.format_version");
101 /**************************************************************************
102 Find and return the first unused unit type user flag. If all unit type
103 user flags are taken MAX_NUM_USER_UNIT_FLAGS is returned.
104 **************************************************************************/
105 static int first_free_unit_type_user_flag(void)
107 int flag;
109 /* Find the first unused user defined unit type flag. */
110 for (flag = 0; flag < MAX_NUM_USER_UNIT_FLAGS; flag++) {
111 if (unit_type_flag_id_name_cb(flag + UTYF_USER_FLAG_1) == NULL) {
112 return flag;
116 /* All unit type user flags are taken. */
117 return MAX_NUM_USER_UNIT_FLAGS;
120 /**************************************************************************
121 Do compatibility things with names before they are referred to. Runs
122 after names are loaded from the ruleset but before the ruleset objects
123 that may refer to them are loaded.
125 This is needed when previously hard coded items that are referred to in
126 the ruleset them self becomes ruleset defined.
128 Returns FALSE if an error occurs.
129 **************************************************************************/
130 bool rscompat_names(struct rscompat_info *info)
132 if (info->ver_units < 20) {
133 /* Some unit type flags moved to the ruleset between 3.0 and 3.1.
134 * Add them back as user flags.
135 * XXX: ruleset might not need all of these, and may have enough
136 * flags of its own that these additional ones prevent conversion. */
137 const struct {
138 const char *name;
139 const char *helptxt;
140 } new_flags_31[] = {
141 { N_("Infra"), N_("Can build infrastructure.") },
144 int first_free;
145 int i;
147 /* Unit type flags. */
148 first_free = first_free_unit_type_user_flag() + UTYF_USER_FLAG_1;
150 for (i = 0; i < ARRAY_SIZE(new_flags_31); i++) {
151 if (UTYF_USER_FLAG_1 + MAX_NUM_USER_UNIT_FLAGS <= first_free + i) {
152 /* Can't add the user unit type flags. */
153 ruleset_error(LOG_ERROR,
154 "Can't upgrade the ruleset. Not enough free unit type "
155 "user flags to add user flags for the unit type flags "
156 "that used to be hardcoded.");
157 return FALSE;
159 /* Shouldn't be possible for valid old ruleset to have flag names that
160 * clash with these ones */
161 if (unit_type_flag_id_by_name(new_flags_31[i].name, fc_strcasecmp)
162 != unit_type_flag_id_invalid()) {
163 ruleset_error(LOG_ERROR,
164 "Ruleset had illegal user unit type flag '%s'",
165 new_flags_31[i].name);
166 return FALSE;
168 set_user_unit_type_flag_name(first_free + i,
169 new_flags_31[i].name,
170 new_flags_31[i].helptxt);
174 /* No errors encountered. */
175 return TRUE;
178 /**************************************************************************
179 Adjust effects
180 **************************************************************************/
181 static bool effect_list_compat_cb(struct effect *peffect, void *data)
183 /* struct rscompat_info *info = (struct rscompat_info *)data; */
185 /* Go to the next effect. */
186 return TRUE;
189 /**************************************************************************
190 Do compatibility things after regular ruleset loading.
191 **************************************************************************/
192 void rscompat_postprocess(struct rscompat_info *info)
194 if (!info->compat_mode) {
195 /* There isn't anything here that should be done outside of compat
196 * mode. */
197 return;
200 /* Upgrade existing effects. Done before new effects are added to prevent
201 * the new effects from being upgraded by accident. */
202 iterate_effect_cache(effect_list_compat_cb, info);
204 if (info->ver_units < 20) {
205 unit_type_iterate(ptype) {
206 if (utype_has_flag(ptype, UTYF_SETTLERS)) {
207 int flag;
209 flag = unit_type_flag_id_by_name("Infra", fc_strcasecmp);
210 fc_assert(unit_type_flag_id_is_valid(flag));
211 BV_SET(ptype->flags, flag);
213 } unit_type_iterate_end;
216 /* The ruleset may need adjustments it didn't need before compatibility
217 * post processing.
219 * If this isn't done a user of ruleset compatibility that ends up using
220 * the rules risks bad rules. A user that saves the ruleset rather than
221 * using it risks an unexpected change on the next load and save. */
222 autoadjust_ruleset_data();
225 /**************************************************************************
226 Replace deprecated requirement type names with currently valid ones.
228 The extra arguments are for situation where some, but not all, instances
229 of a requirement type should become something else.
230 **************************************************************************/
231 const char *rscompat_req_type_name_3_1(const char *old_type,
232 const char *old_range,
233 bool old_survives, bool old_present,
234 bool old_quiet,
235 const char *old_value)
237 return old_type;
240 /**************************************************************************
241 Replace deprecated requirement type names with currently valid ones.
243 The extra arguments are for situation where some, but not all, instances
244 of a requirement type should become something else.
245 **************************************************************************/
246 const char *rscompat_req_name_3_1(const char *type,
247 const char *old_name)
249 if (!fc_strcasecmp("DiplRel", type)
250 && !fc_strcasecmp("Is foreign", old_name)) {
251 return "Foreign";
254 return old_name;
257 /**************************************************************************
258 Replace deprecated unit type flag names with currently valid ones.
259 **************************************************************************/
260 const char *rscompat_utype_flag_name_3_1(struct rscompat_info *compat,
261 const char *old_type)
263 if (compat->compat_mode) {
266 return old_type;