| 1 | #!/usr/bin/env python3 |
| 2 | |
| 3 | """Core options v1 to v2 converter |
| 4 | |
| 5 | Just run this script as follows, to convert 'libretro_core_options.h' & 'Libretro_coreoptions_intl.h' to v2: |
| 6 | python3 "/path/to/v1_to_v2_converter.py" "/path/to/where/libretro_core_options.h & Libretro_coreoptions_intl.h/are" |
| 7 | |
| 8 | The original files will be preserved as *.v1 |
| 9 | """ |
| 10 | import core_option_regex as cor |
| 11 | import os |
| 12 | import sys |
| 13 | |
| 14 | |
| 15 | def create_v2_code_file(struct_text, file_name): |
| 16 | def replace_option(option_match): |
| 17 | _offset = option_match.start(0) |
| 18 | |
| 19 | if option_match.group(3): |
| 20 | res = option_match.group(0)[:option_match.end(2) - _offset] + ',\n NULL' + \ |
| 21 | option_match.group(0)[option_match.end(2) - _offset:option_match.end(3) - _offset] + \ |
| 22 | 'NULL,\n NULL,\n ' + option_match.group(0)[option_match.end(3) - _offset:] |
| 23 | else: |
| 24 | return option_match.group(0) |
| 25 | |
| 26 | return res |
| 27 | |
| 28 | comment_v1 = '/*\n' \ |
| 29 | ' ********************************\n' \ |
| 30 | ' * VERSION: 1.3\n' \ |
| 31 | ' ********************************\n' \ |
| 32 | ' *\n' \ |
| 33 | ' * - 1.3: Move translations to libretro_core_options_intl.h\n' \ |
| 34 | ' * - libretro_core_options_intl.h includes BOM and utf-8\n' \ |
| 35 | ' * fix for MSVC 2010-2013\n' \ |
| 36 | ' * - Added HAVE_NO_LANGEXTRA flag to disable translations\n' \ |
| 37 | ' * on platforms/compilers without BOM support\n' \ |
| 38 | ' * - 1.2: Use core options v1 interface when\n' \ |
| 39 | ' * RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION is >= 1\n' \ |
| 40 | ' * (previously required RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION == 1)\n' \ |
| 41 | ' * - 1.1: Support generation of core options v0 retro_core_option_value\n' \ |
| 42 | ' * arrays containing options with a single value\n' \ |
| 43 | ' * - 1.0: First commit\n' \ |
| 44 | '*/\n' |
| 45 | |
| 46 | comment_v2 = '/*\n' \ |
| 47 | ' ********************************\n' \ |
| 48 | ' * VERSION: 2.0\n' \ |
| 49 | ' ********************************\n' \ |
| 50 | ' *\n' \ |
| 51 | ' * - 2.0: Add support for core options v2 interface\n' \ |
| 52 | ' * - 1.3: Move translations to libretro_core_options_intl.h\n' \ |
| 53 | ' * - libretro_core_options_intl.h includes BOM and utf-8\n' \ |
| 54 | ' * fix for MSVC 2010-2013\n' \ |
| 55 | ' * - Added HAVE_NO_LANGEXTRA flag to disable translations\n' \ |
| 56 | ' * on platforms/compilers without BOM support\n' \ |
| 57 | ' * - 1.2: Use core options v1 interface when\n' \ |
| 58 | ' * RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION is >= 1\n' \ |
| 59 | ' * (previously required RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION == 1)\n' \ |
| 60 | ' * - 1.1: Support generation of core options v0 retro_core_option_value\n' \ |
| 61 | ' * arrays containing options with a single value\n' \ |
| 62 | ' * - 1.0: First commit\n' \ |
| 63 | '*/\n' |
| 64 | |
| 65 | p_intl = cor.p_intl |
| 66 | p_set = cor.p_set |
| 67 | new_set = 'static INLINE void libretro_set_core_options(retro_environment_t environ_cb,\n' \ |
| 68 | ' bool *categories_supported)\n' \ |
| 69 | '{\n' \ |
| 70 | ' unsigned version = 0;\n' \ |
| 71 | '#ifndef HAVE_NO_LANGEXTRA\n' \ |
| 72 | ' unsigned language = 0;\n' \ |
| 73 | '#endif\n' \ |
| 74 | '\n' \ |
| 75 | ' if (!environ_cb || !categories_supported)\n' \ |
| 76 | ' return;\n' \ |
| 77 | '\n' \ |
| 78 | ' *categories_supported = false;\n' \ |
| 79 | '\n' \ |
| 80 | ' if (!environ_cb(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &version))\n' \ |
| 81 | ' version = 0;\n' \ |
| 82 | '\n' \ |
| 83 | ' if (version >= 2)\n' \ |
| 84 | ' {\n' \ |
| 85 | '#ifndef HAVE_NO_LANGEXTRA\n' \ |
| 86 | ' struct retro_core_options_v2_intl core_options_intl;\n' \ |
| 87 | '\n' \ |
| 88 | ' core_options_intl.us = &options_us;\n' \ |
| 89 | ' core_options_intl.local = NULL;\n' \ |
| 90 | '\n' \ |
| 91 | ' if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) &&\n' \ |
| 92 | ' (language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH))\n' \ |
| 93 | ' core_options_intl.local = options_intl[language];\n' \ |
| 94 | '\n' \ |
| 95 | ' *categories_supported = environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL,\n' \ |
| 96 | ' &core_options_intl);\n' \ |
| 97 | '#else\n' \ |
| 98 | ' *categories_supported = environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2,\n' \ |
| 99 | ' &options_us);\n' \ |
| 100 | '#endif\n' \ |
| 101 | ' }\n' \ |
| 102 | ' else\n' \ |
| 103 | ' {\n' \ |
| 104 | ' size_t i, j;\n' \ |
| 105 | ' size_t option_index = 0;\n' \ |
| 106 | ' size_t num_options = 0;\n' \ |
| 107 | ' struct retro_core_option_definition\n' \ |
| 108 | ' *option_v1_defs_us = NULL;\n' \ |
| 109 | '#ifndef HAVE_NO_LANGEXTRA\n' \ |
| 110 | ' size_t num_options_intl = 0;\n' \ |
| 111 | ' struct retro_core_option_v2_definition\n' \ |
| 112 | ' *option_defs_intl = NULL;\n' \ |
| 113 | ' struct retro_core_option_definition\n' \ |
| 114 | ' *option_v1_defs_intl = NULL;\n' \ |
| 115 | ' struct retro_core_options_intl\n' \ |
| 116 | ' core_options_v1_intl;\n' \ |
| 117 | '#endif\n' \ |
| 118 | ' struct retro_variable *variables = NULL;\n' \ |
| 119 | ' char **values_buf = NULL;\n' \ |
| 120 | '\n' \ |
| 121 | ' /* Determine total number of options */\n' \ |
| 122 | ' while (true)\n' \ |
| 123 | ' {\n' \ |
| 124 | ' if (option_defs_us[num_options].key)\n' \ |
| 125 | ' num_options++;\n' \ |
| 126 | ' else\n' \ |
| 127 | ' break;\n' \ |
| 128 | ' }\n' \ |
| 129 | '\n' \ |
| 130 | ' if (version >= 1)\n' \ |
| 131 | ' {\n' \ |
| 132 | ' /* Allocate US array */\n' \ |
| 133 | ' option_v1_defs_us = (struct retro_core_option_definition *)\n' \ |
| 134 | ' calloc(num_options + 1, sizeof(struct retro_core_option_definition));\n' \ |
| 135 | '\n' \ |
| 136 | ' /* Copy parameters from option_defs_us array */\n' \ |
| 137 | ' for (i = 0; i < num_options; i++)\n' \ |
| 138 | ' {\n' \ |
| 139 | ' struct retro_core_option_v2_definition *option_def_us = &option_defs_us[i];\n' \ |
| 140 | ' struct retro_core_option_value *option_values = option_def_us->values;\n' \ |
| 141 | ' struct retro_core_option_definition *option_v1_def_us = &option_v1_defs_us[i];\n' \ |
| 142 | ' struct retro_core_option_value *option_v1_values = option_v1_def_us->values;\n' \ |
| 143 | '\n' \ |
| 144 | ' option_v1_def_us->key = option_def_us->key;\n' \ |
| 145 | ' option_v1_def_us->desc = option_def_us->desc;\n' \ |
| 146 | ' option_v1_def_us->info = option_def_us->info;\n' \ |
| 147 | ' option_v1_def_us->default_value = option_def_us->default_value;\n' \ |
| 148 | '\n' \ |
| 149 | ' /* Values must be copied individually... */\n' \ |
| 150 | ' while (option_values->value)\n' \ |
| 151 | ' {\n' \ |
| 152 | ' option_v1_values->value = option_values->value;\n' \ |
| 153 | ' option_v1_values->label = option_values->label;\n' \ |
| 154 | '\n' \ |
| 155 | ' option_values++;\n' \ |
| 156 | ' option_v1_values++;\n' \ |
| 157 | ' }\n' \ |
| 158 | ' }\n' \ |
| 159 | '\n' \ |
| 160 | '#ifndef HAVE_NO_LANGEXTRA\n' \ |
| 161 | ' if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) &&\n' \ |
| 162 | ' (language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH) &&\n' \ |
| 163 | ' options_intl[language])\n' \ |
| 164 | ' option_defs_intl = options_intl[language]->definitions;\n' \ |
| 165 | '\n' \ |
| 166 | ' if (option_defs_intl)\n' \ |
| 167 | ' {\n' \ |
| 168 | ' /* Determine number of intl options */\n' \ |
| 169 | ' while (true)\n' \ |
| 170 | ' {\n' \ |
| 171 | ' if (option_defs_intl[num_options_intl].key)\n' \ |
| 172 | ' num_options_intl++;\n' \ |
| 173 | ' else\n' \ |
| 174 | ' break;\n' \ |
| 175 | ' }\n' \ |
| 176 | '\n' \ |
| 177 | ' /* Allocate intl array */\n' \ |
| 178 | ' option_v1_defs_intl = (struct retro_core_option_definition *)\n' \ |
| 179 | ' calloc(num_options_intl + 1, sizeof(struct retro_core_option_definition));\n' \ |
| 180 | '\n' \ |
| 181 | ' /* Copy parameters from option_defs_intl array */\n' \ |
| 182 | ' for (i = 0; i < num_options_intl; i++)\n' \ |
| 183 | ' {\n' \ |
| 184 | ' struct retro_core_option_v2_definition *option_def_intl = &option_defs_intl[i];\n' \ |
| 185 | ' struct retro_core_option_value *option_values = option_def_intl->values;\n' \ |
| 186 | ' struct retro_core_option_definition *option_v1_def_intl = &option_v1_defs_intl[i];\n' \ |
| 187 | ' struct retro_core_option_value *option_v1_values = option_v1_def_intl->values;\n' \ |
| 188 | '\n' \ |
| 189 | ' option_v1_def_intl->key = option_def_intl->key;\n' \ |
| 190 | ' option_v1_def_intl->desc = option_def_intl->desc;\n' \ |
| 191 | ' option_v1_def_intl->info = option_def_intl->info;\n' \ |
| 192 | ' option_v1_def_intl->default_value = option_def_intl->default_value;\n' \ |
| 193 | '\n' \ |
| 194 | ' /* Values must be copied individually... */\n' \ |
| 195 | ' while (option_values->value)\n' \ |
| 196 | ' {\n' \ |
| 197 | ' option_v1_values->value = option_values->value;\n' \ |
| 198 | ' option_v1_values->label = option_values->label;\n' \ |
| 199 | '\n' \ |
| 200 | ' option_values++;\n' \ |
| 201 | ' option_v1_values++;\n' \ |
| 202 | ' }\n' \ |
| 203 | ' }\n' \ |
| 204 | ' }\n' \ |
| 205 | '\n' \ |
| 206 | ' core_options_v1_intl.us = option_v1_defs_us;\n' \ |
| 207 | ' core_options_v1_intl.local = option_v1_defs_intl;\n' \ |
| 208 | '\n' \ |
| 209 | ' environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL, &core_options_v1_intl);\n' \ |
| 210 | '#else\n' \ |
| 211 | ' environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS, option_v1_defs_us);\n' \ |
| 212 | '#endif\n' \ |
| 213 | ' }\n' \ |
| 214 | ' else\n' \ |
| 215 | ' {\n' \ |
| 216 | ' /* Allocate arrays */\n' \ |
| 217 | ' variables = (struct retro_variable *)calloc(num_options + 1,\n' \ |
| 218 | ' sizeof(struct retro_variable));\n' \ |
| 219 | ' values_buf = (char **)calloc(num_options, sizeof(char *));\n' \ |
| 220 | '\n' \ |
| 221 | ' if (!variables || !values_buf)\n' \ |
| 222 | ' goto error;\n' \ |
| 223 | '\n' \ |
| 224 | ' /* Copy parameters from option_defs_us array */\n' \ |
| 225 | ' for (i = 0; i < num_options; i++)\n' \ |
| 226 | ' {\n' \ |
| 227 | ' const char *key = option_defs_us[i].key;\n' \ |
| 228 | ' const char *desc = option_defs_us[i].desc;\n' \ |
| 229 | ' const char *default_value = option_defs_us[i].default_value;\n' \ |
| 230 | ' struct retro_core_option_value *values = option_defs_us[i].values;\n' \ |
| 231 | ' size_t buf_len = 3;\n' \ |
| 232 | ' size_t default_index = 0;\n' \ |
| 233 | '\n' \ |
| 234 | ' values_buf[i] = NULL;\n' \ |
| 235 | '\n' \ |
| 236 | ' if (desc)\n' \ |
| 237 | ' {\n' \ |
| 238 | ' size_t num_values = 0;\n' \ |
| 239 | '\n' \ |
| 240 | ' /* Determine number of values */\n' \ |
| 241 | ' while (true)\n' \ |
| 242 | ' {\n' \ |
| 243 | ' if (values[num_values].value)\n' \ |
| 244 | ' {\n' \ |
| 245 | ' /* Check if this is the default value */\n' \ |
| 246 | ' if (default_value)\n' \ |
| 247 | ' if (strcmp(values[num_values].value, default_value) == 0)\n' \ |
| 248 | ' default_index = num_values;\n' \ |
| 249 | '\n' \ |
| 250 | ' buf_len += strlen(values[num_values].value);\n' \ |
| 251 | ' num_values++;\n' \ |
| 252 | ' }\n' \ |
| 253 | ' else\n' \ |
| 254 | ' break;\n' \ |
| 255 | ' }\n' \ |
| 256 | '\n' \ |
| 257 | ' /* Build values string */\n' \ |
| 258 | ' if (num_values > 0)\n' \ |
| 259 | ' {\n' \ |
| 260 | ' buf_len += num_values - 1;\n' \ |
| 261 | ' buf_len += strlen(desc);\n' \ |
| 262 | '\n' \ |
| 263 | ' values_buf[i] = (char *)calloc(buf_len, sizeof(char));\n' \ |
| 264 | ' if (!values_buf[i])\n' \ |
| 265 | ' goto error;\n' \ |
| 266 | '\n' \ |
| 267 | ' strcpy(values_buf[i], desc);\n' \ |
| 268 | ' strcat(values_buf[i], "; ");\n' \ |
| 269 | '\n' \ |
| 270 | ' /* Default value goes first */\n' \ |
| 271 | ' strcat(values_buf[i], values[default_index].value);\n' \ |
| 272 | '\n' \ |
| 273 | ' /* Add remaining values */\n' \ |
| 274 | ' for (j = 0; j < num_values; j++)\n' \ |
| 275 | ' {\n' \ |
| 276 | ' if (j != default_index)\n' \ |
| 277 | ' {\n' \ |
| 278 | ' strcat(values_buf[i], "|");\n' \ |
| 279 | ' strcat(values_buf[i], values[j].value);\n' \ |
| 280 | ' }\n' \ |
| 281 | ' }\n' \ |
| 282 | ' }\n' \ |
| 283 | ' }\n' \ |
| 284 | '\n' \ |
| 285 | ' variables[option_index].key = key;\n' \ |
| 286 | ' variables[option_index].value = values_buf[i];\n' \ |
| 287 | ' option_index++;\n' \ |
| 288 | ' }\n' \ |
| 289 | '\n' \ |
| 290 | ' /* Set variables */\n' \ |
| 291 | ' environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables);\n' \ |
| 292 | ' }\n' \ |
| 293 | '\n' \ |
| 294 | 'error:\n' \ |
| 295 | ' /* Clean up */\n' \ |
| 296 | '\n' \ |
| 297 | ' if (option_v1_defs_us)\n' \ |
| 298 | ' {\n' \ |
| 299 | ' free(option_v1_defs_us);\n' \ |
| 300 | ' option_v1_defs_us = NULL;\n' \ |
| 301 | ' }\n' \ |
| 302 | '\n' \ |
| 303 | '#ifndef HAVE_NO_LANGEXTRA\n' \ |
| 304 | ' if (option_v1_defs_intl)\n' \ |
| 305 | ' {\n' \ |
| 306 | ' free(option_v1_defs_intl);\n' \ |
| 307 | ' option_v1_defs_intl = NULL;\n' \ |
| 308 | ' }\n' \ |
| 309 | '#endif\n' \ |
| 310 | '\n' \ |
| 311 | ' if (values_buf)\n' \ |
| 312 | ' {\n' \ |
| 313 | ' for (i = 0; i < num_options; i++)\n' \ |
| 314 | ' {\n' \ |
| 315 | ' if (values_buf[i])\n' \ |
| 316 | ' {\n' \ |
| 317 | ' free(values_buf[i]);\n' \ |
| 318 | ' values_buf[i] = NULL;\n' \ |
| 319 | ' }\n' \ |
| 320 | ' }\n' \ |
| 321 | '\n' \ |
| 322 | ' free(values_buf);\n' \ |
| 323 | ' values_buf = NULL;\n' \ |
| 324 | ' }\n' \ |
| 325 | '\n' \ |
| 326 | ' if (variables)\n' \ |
| 327 | ' {\n' \ |
| 328 | ' free(variables);\n' \ |
| 329 | ' variables = NULL;\n' \ |
| 330 | ' }\n' \ |
| 331 | ' }\n' \ |
| 332 | '}\n' \ |
| 333 | '\n' \ |
| 334 | '#ifdef __cplusplus\n' \ |
| 335 | '}\n' \ |
| 336 | '#endif' |
| 337 | |
| 338 | struct_groups = cor.p_struct.finditer(struct_text) |
| 339 | out_text = struct_text |
| 340 | |
| 341 | for construct in struct_groups: |
| 342 | repl_text = '' |
| 343 | declaration = construct.group(1) |
| 344 | struct_match = cor.p_type_name.search(declaration) |
| 345 | if struct_match: |
| 346 | if struct_match.group(3): |
| 347 | struct_type_name_lang = struct_match.group(1, 2, 3) |
| 348 | declaration_end = declaration[struct_match.end(1):] |
| 349 | elif struct_match.group(4): |
| 350 | struct_type_name_lang = struct_match.group(1, 2, 4) |
| 351 | declaration_end = declaration[struct_match.end(1):] |
| 352 | else: |
| 353 | struct_type_name_lang = sum((struct_match.group(1, 2), ('_us',)), ()) |
| 354 | declaration_end = f'{declaration[struct_match.end(1):struct_match.end(2)]}_us' \ |
| 355 | f'{declaration[struct_match.end(2):]}' |
| 356 | else: |
| 357 | return -1 |
| 358 | |
| 359 | if 'retro_core_option_definition' == struct_type_name_lang[0]: |
| 360 | import shutil |
| 361 | shutil.copy(file_name, file_name + '.v1') |
| 362 | new_declaration = f'\nstruct retro_core_option_v2_category option_cats{struct_type_name_lang[2]}[] = ' \ |
| 363 | '{\n { NULL, NULL, NULL },\n' \ |
| 364 | '};\n\n' \ |
| 365 | + declaration[:struct_match.start(1)] + \ |
| 366 | 'retro_core_option_v2_definition' \ |
| 367 | + declaration_end |
| 368 | offset = construct.start(0) |
| 369 | repl_text = repl_text + cor.re.sub(cor.re.escape(declaration), new_declaration, |
| 370 | construct.group(0)[:construct.start(2) - offset]) |
| 371 | content = construct.group(2) |
| 372 | new_content = cor.p_option.sub(replace_option, content) |
| 373 | |
| 374 | repl_text = repl_text + new_content + cor.re.sub(r'{\s*NULL,\s*NULL,\s*NULL,\s*{\{0}},\s*NULL\s*},\s*};', |
| 375 | '{ NULL, NULL, NULL, NULL, NULL, NULL, {{0}}, NULL },\n};' |
| 376 | '\n\nstruct retro_core_options_v2 options' + |
| 377 | struct_type_name_lang[2] + ' = {\n' |
| 378 | f' option_cats{struct_type_name_lang[2]},\n' |
| 379 | f' option_defs{struct_type_name_lang[2]}\n' |
| 380 | '};', |
| 381 | construct.group(0)[construct.end(2) - offset:]) |
| 382 | out_text = cor.re.sub(cor.re.escape(construct.group(0)), repl_text, out_text) |
| 383 | else: |
| 384 | return -2 |
| 385 | with open(file_name, 'w', encoding='utf-8') as code_file: |
| 386 | out_text = cor.re.sub(cor.re.escape(comment_v1), comment_v2, out_text) |
| 387 | intl = p_intl.search(out_text) |
| 388 | if intl: |
| 389 | new_intl = out_text[:intl.start(1)] \ |
| 390 | + 'struct retro_core_options_v2 *options_intl[RETRO_LANGUAGE_LAST]' \ |
| 391 | + out_text[intl.end(1):intl.start(2)] \ |
| 392 | + '&options_us, /* RETRO_LANGUAGE_ENGLISH */' \ |
| 393 | ' &options_ja, /* RETRO_LANGUAGE_JAPANESE */' \ |
| 394 | ' &options_fr, /* RETRO_LANGUAGE_FRENCH */' \ |
| 395 | ' &options_es, /* RETRO_LANGUAGE_SPANISH */' \ |
| 396 | ' &options_de, /* RETRO_LANGUAGE_GERMAN */' \ |
| 397 | ' &options_it, /* RETRO_LANGUAGE_ITALIAN */' \ |
| 398 | ' &options_nl, /* RETRO_LANGUAGE_DUTCH */' \ |
| 399 | ' &options_pt_br, /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */' \ |
| 400 | ' &options_pt_pt, /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */' \ |
| 401 | ' &options_ru, /* RETRO_LANGUAGE_RUSSIAN */' \ |
| 402 | ' &options_ko, /* RETRO_LANGUAGE_KOREAN */' \ |
| 403 | ' &options_cht, /* RETRO_LANGUAGE_CHINESE_TRADITIONAL */' \ |
| 404 | ' &options_chs, /* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */' \ |
| 405 | ' &options_eo, /* RETRO_LANGUAGE_ESPERANTO */' \ |
| 406 | ' &options_pl, /* RETRO_LANGUAGE_POLISH */' \ |
| 407 | ' &options_vn, /* RETRO_LANGUAGE_VIETNAMESE */' \ |
| 408 | ' &options_ar, /* RETRO_LANGUAGE_ARABIC */' \ |
| 409 | ' &options_el, /* RETRO_LANGUAGE_GREEK */' \ |
| 410 | ' &options_tr, /* RETRO_LANGUAGE_TURKISH */' \ |
| 411 | ' &options_sv, /* RETRO_LANGUAGE_SLOVAK */' \ |
| 412 | ' &options_fa, /* RETRO_LANGUAGE_PERSIAN */' \ |
| 413 | ' &options_he, /* RETRO_LANGUAGE_HEBREW */' \ |
| 414 | ' &options_ast, /* RETRO_LANGUAGE_ASTURIAN */' \ |
| 415 | ' &options_fi, /* RETRO_LANGUAGE_FINNISH */' \ |
| 416 | + out_text[intl.end(2):] |
| 417 | out_text = p_set.sub(new_set, new_intl) |
| 418 | else: |
| 419 | out_text = p_set.sub(new_set, out_text) |
| 420 | code_file.write(out_text) |
| 421 | |
| 422 | return 1 |
| 423 | |
| 424 | |
| 425 | # -------------------- MAIN -------------------- # |
| 426 | |
| 427 | if __name__ == '__main__': |
| 428 | try: |
| 429 | if os.path.isfile(sys.argv[1]): |
| 430 | _temp = os.path.dirname(sys.argv[1]) |
| 431 | else: |
| 432 | _temp = sys.argv[1] |
| 433 | while _temp.endswith('/') or _temp.endswith('\\'): |
| 434 | _temp = _temp[:-1] |
| 435 | DIR_PATH = _temp |
| 436 | except IndexError: |
| 437 | DIR_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) |
| 438 | print("No path provided, assuming parent directory:\n" + DIR_PATH) |
| 439 | |
| 440 | H_FILE_PATH = os.path.join(DIR_PATH, 'libretro_core_options.h') |
| 441 | INTL_FILE_PATH = os.path.join(DIR_PATH, 'libretro_core_options_intl.h') |
| 442 | |
| 443 | for file in (H_FILE_PATH, INTL_FILE_PATH): |
| 444 | if os.path.isfile(file): |
| 445 | with open(file, 'r+', encoding='utf-8') as h_file: |
| 446 | text = h_file.read() |
| 447 | try: |
| 448 | test = create_v2_code_file(text, file) |
| 449 | except Exception as e: |
| 450 | print(e) |
| 451 | test = -1 |
| 452 | if -1 > test: |
| 453 | print('Your file looks like it already is v2? (' + file + ')') |
| 454 | continue |
| 455 | if 0 > test: |
| 456 | print('An error occured! Please make sure to use the complete v1 struct! (' + file + ')') |
| 457 | continue |
| 458 | else: |
| 459 | print(file + ' not found.') |