errors.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "errors.h" | ||
| 2 | |||
| 3 | #include "asar.h" | ||
| 4 | #include <assert.h> | ||
| 5 | #include <stdarg.h> | ||
| 6 | |||
| 7 | #include "interface-shared.h" | ||
| 8 | |||
| 9 | static int asar_num_errors = 0; | ||
| 10 | |||
| 11 | struct asar_error_mapping | ||
| 12 | { | ||
| 13 | asar_error_id errid; | ||
| 14 | const char* name; | ||
| 15 | const char* message; | ||
| 16 | |||
| 17 | 42200 | asar_error_mapping(asar_error_id inerrid, const char* iname, const char* inmessage) | |
| 18 | 42200 | { | |
| 19 | 42200 | ++asar_num_errors; | |
| 20 | |||
| 21 | 42200 | errid = inerrid; | |
| 22 | 42200 | name = iname; | |
| 23 | 42200 | message = inmessage; | |
| 24 | |||
| 25 | // RPG Hacker: Sanity check. This makes sure that the order | ||
| 26 | // of entries in asar_errors matches with the order of | ||
| 27 | // constants in asar_error_id. This is important because | ||
| 28 | // we access asar_errors as an array. | ||
| 29 | // Would love to do this via static_assert(), but can't | ||
| 30 | // think of a way to do so. | ||
| 31 | 42200 | assert(errid - error_id_start == asar_num_errors); | |
| 32 | 42200 | } | |
| 33 | }; | ||
| 34 | |||
| 35 | // Keep in sync with asar_error_id. | ||
| 36 | // Both, enum mapping and order, must match. | ||
| 37 | #define ERR(name) error_id_ ## name, "E" #name | ||
| 38 | static asar_error_mapping asar_errors[] = | ||
| 39 | { | ||
| 40 | { ERR(limit_reached), "Over %d errors detected. Aborting." }, | ||
| 41 | { ERR(werror), "One or more warnings was detected with werror on." }, | ||
| 42 | |||
| 43 | { ERR(16mb_rom_limit), "Can't create ROMs larger than 16MB." }, | ||
| 44 | { ERR(buffer_too_small), "The given buffer is too small to contain the resulting ROM." }, | ||
| 45 | { ERR(params_null), "params passed to asar_patch_ex() is null." }, | ||
| 46 | { ERR(params_invalid_size), "Size of params passed to asar_patch_ex() is invalid." }, | ||
| 47 | { ERR(cmdl_define_invalid), "Invalid define name in %s: '%s'." }, | ||
| 48 | { ERR(cmdl_define_override), "%s '%s' overrides a previous define. Did you specify the same define twice?" }, | ||
| 49 | { ERR(create_rom_failed), "Couldn't create ROM." }, | ||
| 50 | { ERR(open_rom_failed), "Couldn't open ROM." }, | ||
| 51 | { ERR(open_rom_not_smw_extension), "Doesn't look like an SMW ROM. (Maybe its extension is wrong?)" }, | ||
| 52 | { ERR(open_rom_not_smw_header), "Doesn't look like an SMW ROM. (Maybe it's headered?)" }, | ||
| 53 | { ERR(stddefines_no_identifier), "stddefines.txt contains a line with a value, but no identifier." }, | ||
| 54 | { ERR(stddefine_after_closing_quote), "Broken std defines. (Something after closing quote)" }, | ||
| 55 | |||
| 56 | { ERR(failed_to_open_file), "Failed to open file '%s'." }, | ||
| 57 | { ERR(file_not_found), "File '%s' wasn't found." }, | ||
| 58 | { ERR(readfile_1_to_4_bytes), "Can only read chunks of 1 to 4 bytes." }, | ||
| 59 | { ERR(canreadfile_0_bytes), "Number of bytes to check must be > 0." }, | ||
| 60 | { ERR(file_offset_out_of_bounds), "File offset %s out of bounds for file '%s'." }, | ||
| 61 | { ERR(rep_at_file_end), "rep at the end of a file" }, | ||
| 62 | |||
| 63 | { ERR(mismatched_parentheses), "Mismatched parentheses." }, | ||
| 64 | { ERR(invalid_hex_value), "Invalid hex value." }, | ||
| 65 | { ERR(invalid_binary_value), "Invalid binary value." }, | ||
| 66 | { ERR(invalid_character), "Invalid character." }, | ||
| 67 | { ERR(string_literal_not_terminated), "String literal not terminated." }, | ||
| 68 | { ERR(malformed_function_call), "Malformed function call." }, | ||
| 69 | { ERR(invalid_number), "Invalid number." }, | ||
| 70 | { ERR(garbage_near_quoted_string), "Garbage near quoted string." }, | ||
| 71 | { ERR(mismatched_quotes), "Mismatched quotes." }, | ||
| 72 | |||
| 73 | { ERR(rom_too_short), "ROM is too short to have a title. (Expected '%s')" }, | ||
| 74 | { ERR(rom_title_incorrect), "ROM title is incorrect. Expected '%s', got '%s'." }, | ||
| 75 | |||
| 76 | { ERR(bank_border_crossed), "A bank border was crossed, SNES address $%06X." }, | ||
| 77 | |||
| 78 | { ERR(start_of_file), "This command may only be used at the start of a file." }, | ||
| 79 | { ERR(xkas_asar_conflict), "Using @xkas and @asar in the same patch is not supported." }, | ||
| 80 | { ERR(invalid_version_number), "Invalid version number." }, | ||
| 81 | { ERR(asar_too_old), "This version of Asar is too old for this patch." }, | ||
| 82 | |||
| 83 | { ERR(relative_branch_out_of_bounds), "Relative branch out of bounds. (Distance is %s)." }, | ||
| 84 | { ERR(snes_address_doesnt_map_to_rom), "SNES address %s doesn't map to ROM." }, | ||
| 85 | { ERR(snes_address_out_of_bounds), "SNES address %s out of bounds." }, | ||
| 86 | { ERR(invalid_tcall), "Invalid tcall." }, | ||
| 87 | { ERR(use_xplus), "Use (x+) instead." }, | ||
| 88 | { ERR(opcode_length_too_long), "Opcode length is too long." }, | ||
| 89 | { ERR(superfx_invalid_short_address), "Invalid short address parameter: $%s. (Must be even number and $0000-$01FE)" }, | ||
| 90 | { ERR(superfx_invalid_register), "Invalid register for opcode; valid range is %d-%d." }, | ||
| 91 | { ERR(invalid_opcode_length), "Invalid opcode length specification." }, | ||
| 92 | { ERR(invalid_mapper), "Invalid mapper." }, | ||
| 93 | |||
| 94 | { ERR(nan), "NaN encountered." }, | ||
| 95 | { ERR(division_by_zero), "Division by zero." }, | ||
| 96 | { ERR(modulo_by_zero), "Modulo by zero." }, | ||
| 97 | { ERR(unknown_operator), "Unknown operator." }, | ||
| 98 | { ERR(invalid_input), "Invalid input." }, | ||
| 99 | |||
| 100 | { ERR(invalid_function_name), "Invalid function name." }, | ||
| 101 | { ERR(function_not_found), "Function '%s' wasn't found." }, | ||
| 102 | { ERR(function_redefined), "Function '%s' redefined." }, | ||
| 103 | { ERR(broken_function_declaration), "Broken function declaration." }, | ||
| 104 | { ERR(wrong_num_parameters), "Wrong number of parameters to function." }, | ||
| 105 | { ERR(invalid_param_name), "Invalid parameter name." }, | ||
| 106 | { ERR(math_invalid_type), "Wrong type for parameter %s, expected %s." }, | ||
| 107 | |||
| 108 | { ERR(invalid_label_name), "Invalid label name." }, | ||
| 109 | { ERR(label_not_found), "Label '%s' wasn't found." }, | ||
| 110 | { ERR(label_redefined), "Label '%s' redefined." }, | ||
| 111 | { ERR(broken_label_definition), "Broken label definition." }, | ||
| 112 | { ERR(label_cross_assignment), "Setting labels to other non-static labels is not valid." }, | ||
| 113 | { ERR(macro_label_outside_of_macro), "Macro label outside of a macro." }, | ||
| 114 | { ERR(label_on_third_pass), "Internal error: A label was created on the third pass. Please create an issue on the official GitHub repository and attach a patch which reproduces the error." }, | ||
| 115 | { ERR(label_moving), "Internal error: A label is moving around. Please create an issue on the official GitHub repository and attach a patch which reproduces the error." }, | ||
| 116 | |||
| 117 | { ERR(invalid_namespace_name), "Invalid namespace name." }, | ||
| 118 | { ERR(invalid_namespace_use), "Invalid use of namespace command." }, | ||
| 119 | |||
| 120 | { ERR(invalid_struct_name), "Invalid struct name." }, | ||
| 121 | { ERR(struct_not_found), "Struct '%s' wasn't found." }, | ||
| 122 | { ERR(struct_redefined), "Struct '%s' redefined." }, | ||
| 123 | { ERR(struct_invalid_parent_name), "Invalid parent name." }, | ||
| 124 | { ERR(invalid_label_missing_closer), "Invalid label name, missing array closer." }, | ||
| 125 | { ERR(multiple_subscript_operators), "Multiple subscript operators is invalid." }, | ||
| 126 | { ERR(invalid_subscript), "Invalid array subscript after first scope resolution." }, | ||
| 127 | { ERR(label_missing_parent), "This label has no parent." }, | ||
| 128 | { ERR(array_invalid_inside_structs), "Array syntax invalid inside structs." }, | ||
| 129 | { ERR(struct_without_endstruct), "struct without matching endstruct." }, | ||
| 130 | { ERR(nested_struct), "Can not nest structs." }, | ||
| 131 | { ERR(missing_struct_params), "Missing struct parameters." }, | ||
| 132 | { ERR(too_many_struct_params), "Too many struct parameters." }, | ||
| 133 | { ERR(missing_extends), "Missing extends keyword." }, | ||
| 134 | { ERR(invalid_endstruct_count), "Invalid endstruct parameter count." }, | ||
| 135 | { ERR(expected_align), "Expected align parameter." }, | ||
| 136 | { ERR(endstruct_without_struct), "endstruct can only be used in combination with struct." }, | ||
| 137 | { ERR(alignment_too_small), "Alignment must be >= 1." }, | ||
| 138 | |||
| 139 | { ERR(invalid_define_name), "Invalid define name." }, | ||
| 140 | { ERR(define_not_found), "Define '%s' wasn't found." }, | ||
| 141 | { ERR(broken_define_declaration), "Broken define declaration." }, | ||
| 142 | { ERR(overriding_builtin_define), "Trying to set define '%s', which is the name of a built-in define and thus can't be modified." }, | ||
| 143 | { ERR(define_label_math), "!Define #= Label is not allowed with non-static labels." }, | ||
| 144 | { ERR(mismatched_braces), "Mismatched braces." }, | ||
| 145 | |||
| 146 | { ERR(invalid_macro_name), "Invalid macro name." }, | ||
| 147 | { ERR(macro_not_found), "Macro '%s' wasn't found." }, | ||
| 148 | { ERR(macro_redefined), "Macro '%s' redefined." }, | ||
| 149 | { ERR(broken_macro_declaration), "Broken macro declaration." }, | ||
| 150 | { ERR(invalid_macro_param_name), "Invalid macro parameter name." }, | ||
| 151 | { ERR(macro_param_not_found), "Macro parameter '%s' wasn't found." }, | ||
| 152 | { ERR(macro_param_redefined), "Macro parameter '%s' redefined" }, | ||
| 153 | { ERR(broken_macro_usage), "Broken macro usage." }, | ||
| 154 | { ERR(macro_wrong_num_params), "Wrong number of parameters to macro." }, | ||
| 155 | { ERR(broken_macro_contents), "Broken macro contents." }, | ||
| 156 | { ERR(rep_at_macro_end), "rep or if at the end of a macro." }, | ||
| 157 | { ERR(nested_macro_definition), "Nested macro definition." }, | ||
| 158 | { ERR(misplaced_endmacro), "Misplaced endmacro." }, | ||
| 159 | { ERR(unclosed_macro), "Unclosed macro." }, | ||
| 160 | |||
| 161 | { ERR(label_in_conditional), "Non-static label in %s command." }, | ||
| 162 | { ERR(broken_conditional), "Broken %s command." }, | ||
| 163 | { ERR(invalid_condition), "Invalid condition." }, | ||
| 164 | { ERR(misplaced_elseif), "Misplaced elseif." }, | ||
| 165 | { ERR(elseif_in_while), "Can't use elseif in a while loop." }, | ||
| 166 | { ERR(elseif_in_singleline), "Can't use elseif on single-line statements." }, | ||
| 167 | { ERR(misplaced_endif), "Misplaced endif." }, | ||
| 168 | { ERR(misplaced_else), "Misplaced else." }, | ||
| 169 | { ERR(else_in_while_loop), "Can't use else in a while loop." }, | ||
| 170 | { ERR(unclosed_if), "Unclosed if statement." }, | ||
| 171 | |||
| 172 | { ERR(unknown_command), "Unknown command." }, | ||
| 173 | { ERR(command_disabled), "This command is disabled." }, | ||
| 174 | |||
| 175 | { ERR(broken_incbin), "Broken incbin command." }, | ||
| 176 | { ERR(incbin_64kb_limit), "Can't include more than 64 kilobytes at once." }, | ||
| 177 | { ERR(recursion_limit), "Recursion limit reached." }, | ||
| 178 | { ERR(command_in_non_root_file), "This command may only be used in the root file." }, | ||
| 179 | { ERR(cant_be_main_file), "This file may not be used as the main file.%s" }, | ||
| 180 | { ERR(no_labels_here), "Can't use non-static labels here." }, | ||
| 181 | |||
| 182 | { ERR(invalid_freespace_request), "Invalid freespace request." }, | ||
| 183 | { ERR(no_banks_with_ram_mirrors), "No banks contain the RAM mirrors in hirom or exhirom." }, | ||
| 184 | { ERR(no_freespace_norom), "Can't find freespace in norom." }, | ||
| 185 | { ERR(static_freespace_autoclean), "A static freespace must be targeted by at least one autoclean." }, | ||
| 186 | { ERR(static_freespace_growing), "A static freespace may not grow." }, | ||
| 187 | { ERR(no_freespace_in_mapped_banks), "No freespace found in the mapped banks. (Requested size: %s)" }, | ||
| 188 | { ERR(no_freespace), "No freespace found. (Requested size: %s)" }, | ||
| 189 | { ERR(freespace_limit_reached), "A patch may not contain more than %d freespaces." }, | ||
| 190 | |||
| 191 | { ERR(prot_not_at_freespace_start), "PROT must be used at the start of a freespace block." }, | ||
| 192 | { ERR(prot_too_many_entries), "Too many entries to PROT." }, | ||
| 193 | |||
| 194 | { ERR(autoclean_in_freespace), "autoclean used in freespace." }, | ||
| 195 | { ERR(autoclean_label_at_freespace_end), "Don't autoclean a label at the end of a freespace block, you'll remove some stuff you're not supposed to remove." }, | ||
| 196 | { ERR(broken_autoclean), "Broken autoclean command." }, | ||
| 197 | |||
| 198 | { ERR(pulltable_without_table), "Using pulltable when there is no table on the stack yet." }, | ||
| 199 | { ERR(invalid_table_file), "Invalid table file. Invalid entry on line: %i" }, | ||
| 200 | |||
| 201 | { ERR(pad_in_freespace), "pad does not make sense in a freespaced code." }, | ||
| 202 | |||
| 203 | { ERR(org_label_invalid), "org Label is not valid." }, | ||
| 204 | { ERR(org_label_forward), "org Label is only valid for labels earlier in the patch." }, | ||
| 205 | |||
| 206 | { ERR(skip_label_invalid), "skip Label is not valid." }, | ||
| 207 | |||
| 208 | { ERR(spc700_inline_no_base), "base is not implemented for architecture spc700-inline." }, | ||
| 209 | { ERR(base_label_invalid), "base Label is not valid." }, | ||
| 210 | |||
| 211 | { ERR(rep_label), "rep Label is not valid." }, | ||
| 212 | |||
| 213 | { ERR(pushpc_without_pullpc), "pushpc without matching pullpc." }, | ||
| 214 | { ERR(pullpc_without_pushpc), "pullpc without matching pushpc." }, | ||
| 215 | { ERR(pullpc_different_arch), "pullpc in another architecture than the pushpc." }, | ||
| 216 | { ERR(pullbase_without_pushbase), "pullbase without matching pushbase." }, | ||
| 217 | |||
| 218 | { ERR(invalid_math), "Invalid math command." }, | ||
| 219 | { ERR(invalid_warn), "Invalid warn command." }, | ||
| 220 | { ERR(invalid_check), "Invalid check command." }, | ||
| 221 | |||
| 222 | { ERR(warnpc_in_freespace), "warnpc used in freespace." }, | ||
| 223 | { ERR(warnpc_broken_param), "Broken warnpc parameter." }, | ||
| 224 | { ERR(warnpc_failed), "warnpc failed: Current position (%s) is after end position (%s)." }, | ||
| 225 | { ERR(warnpc_failed_equal), "warnpc failed: Current position (%s) is equal to end position (%s)." }, | ||
| 226 | |||
| 227 | { ERR(assertion_failed), "Assertion failed%s" }, | ||
| 228 | |||
| 229 | { ERR(error_command), "error command%s" }, | ||
| 230 | |||
| 231 | { ERR(invalid_print_function_syntax), "Invalid printable string syntax." }, | ||
| 232 | { ERR(unknown_variable), "Unknown variable." }, | ||
| 233 | |||
| 234 | { ERR(invalid_warning_id), "Invalid warning ID passed to %s. Expected format is WXXXX where %d <= XXXX <= %d." }, | ||
| 235 | |||
| 236 | { ERR(pushwarnings_without_pullwarnings), "warnings push without matching warnings pull." }, | ||
| 237 | { ERR(pullwarnings_without_pushwarnings), "warnings pull without matching warnings push." }, | ||
| 238 | |||
| 239 | { ERR(failed_to_open_file_access_denied), "Failed to open file '%s'. Access denied." }, | ||
| 240 | { ERR(failed_to_open_not_regular_file), "Failed to open file '%s'. Not a regular file (did you try to use a directory?)" }, | ||
| 241 | |||
| 242 | { ERR(bad_dp_base), "The dp base should be page aligned (i.e. a multiple of 256)"}, | ||
| 243 | { ERR(bad_dp_optimize), "Bad dp optimize value %s, expected: [none, ram, always]"}, | ||
| 244 | { ERR(bad_address_optimize), "Bad dp optimize value %s, expected: [default, ram, mirrors]"}, | ||
| 245 | { ERR(bad_optimize), "Bad optimize value %s, expected: [dp, address]"}, | ||
| 246 | |||
| 247 | { ERR(require_parameter), "Missing required function parameter"}, | ||
| 248 | { ERR(expected_parameter), "Not enough parameters in calling of function %s"}, | ||
| 249 | { ERR(unexpected_parameter), "Too many parameters in calling of function %s"}, | ||
| 250 | { ERR(duplicate_param_name), "Duplicated parameter name: %s in creation of function %s"}, | ||
| 251 | |||
| 252 | { ERR(invalid_alignment), "Invalid alignment. Expected a power of 2." }, | ||
| 253 | { ERR(alignment_too_big), "Requested alignment too large." }, | ||
| 254 | |||
| 255 | { ERR(negative_shift), "Bitshift amount is negative." }, | ||
| 256 | |||
| 257 | { ERR(macro_not_varadic), "Invalid use of sizeof(...), active macro is not variadic." }, | ||
| 258 | { ERR(vararg_sizeof_nomacro), "Invalid use of sizeof(...), no active macro." }, | ||
| 259 | { ERR(macro_wrong_min_params), "Variadic macro call with too few parameters" }, | ||
| 260 | { ERR(vararg_out_of_bounds), "Variadic macro parameter requested is out of bounds." }, | ||
| 261 | { ERR(vararg_must_be_last), "Variadic macro parameter must be the last parameter." }, | ||
| 262 | { ERR(invalid_global_label), "Global label definition contains an invalid label [%s]."}, | ||
| 263 | |||
| 264 | { ERR(spc700_addr_out_of_range), "Address %s out of range for instruction, valid range is 0000-1FFF" }, | ||
| 265 | { ERR(label_ambiguous), "Label (%s) location is ambiguous due to straddling optimization border." }, | ||
| 266 | |||
| 267 | { ERR(feature_unavaliable_in_spcblock), "This feature may not be used while an spcblock is active" }, | ||
| 268 | { ERR(endspcblock_without_spcblock), "Use of endspcblock without matching spcblock" }, | ||
| 269 | { ERR(missing_endspcblock), "Use of endspcblock without matching spcblock" }, | ||
| 270 | { ERR(spcblock_bad_arch), "spcblock only valid inside spc700 arch" }, | ||
| 271 | { ERR(spcblock_inside_struct), "Can not start an spcblock while a struct is still open" }, | ||
| 272 | { ERR(spcblock_too_few_args), "Too few args passed to spcblock" }, | ||
| 273 | { ERR(spcblock_too_many_args), "Too many args passed to spcblock" }, | ||
| 274 | { ERR(unknown_spcblock_type), "Unknown spcblock format" }, | ||
| 275 | { ERR(custom_spcblock_missing_macro), "Custom spcblock types must refer to a valid macro" }, | ||
| 276 | { ERR(spcblock_macro_doesnt_exist), "Macro specified to custom spcblock was not found"}, | ||
| 277 | { ERR(extra_spcblock_arg_for_type), "Only custom spcblock type takes a fourth argument" }, | ||
| 278 | { ERR(spcblock_macro_must_be_varadic), "Custom spcblock macros must be variadic" }, | ||
| 279 | { ERR(spcblock_macro_invalid_static_args), "Custom spcblock macros must have three static arguments" }, | ||
| 280 | { ERR(spcblock_custom_types_incomplete), "Custom spcblock types are not yet supported. One day." }, | ||
| 281 | { ERR(startpos_without_spcblock), "The startpos command is only valid in spcblocks" }, | ||
| 282 | { ERR(invalid_endspcblock_arg), "Invalid argument to endspcblock: \"%s\"" }, | ||
| 283 | { ERR(unknown_endspcblock_format), "Unsupported endspcblock format. Currently supported formats are \"endspcblock\" and \"endspcblock execute [label]\"" }, | ||
| 284 | { ERR(internal_error), "An internal asar error occured (%s). Send help." }, | ||
| 285 | |||
| 286 | { ERR(pushns_without_pullns), "pushns without matching pullns." }, | ||
| 287 | { ERR(pullns_without_pushns), "pullns without matching pushns." }, | ||
| 288 | |||
| 289 | { ERR(label_forward), "The use of forward labels is not allowed in this context." }, | ||
| 290 | |||
| 291 | { ERR(unclosed_vararg), "Variadic macro parameter wasn't closed properly." }, | ||
| 292 | { ERR(invalid_vararg), "Trying to use variadic macro parameter syntax to resolve a non variadic argument." }, | ||
| 293 | |||
| 294 | { ERR(macro_param_outside_macro), "Reference to macro parameter outside of macro" }, | ||
| 295 | |||
| 296 | { ERR(broken_for_loop), "Broken for loop declaration." }, | ||
| 297 | { ERR(bad_single_line_for), "Single-line for loop not allowed here." }, | ||
| 298 | |||
| 299 | }; | ||
| 300 | // RPG Hacker: Sanity check. This makes sure that the element count of asar_warnings | ||
| 301 | // matches with the number of constants in asar_warning_id. This is important, because | ||
| 302 | // we are going to access asar_warnings as an array. | ||
| 303 | static_assert(sizeof(asar_errors) / sizeof(asar_errors[0]) == error_id_count, "asar_errors and asar_error_id are not in sync"); | ||
| 304 | |||
| 305 | template<typename t> | ||
| 306 | 218 | void asar_error_template(asar_error_id errid, int whichpass, const char* message) | |
| 307 | { | ||
| 308 | try | ||
| 309 | { | ||
| 310 | 218 | error_interface((int)errid, whichpass, message); | |
| 311 | 109 | t err; | |
| 312 | 218 | throw err; | |
| 313 | } | ||
| 314 | 218 | catch (errnull&) {} | |
| 315 | 8 | } | |
| 316 | |||
| 317 | #if !defined(__clang__) | ||
| 318 | void(*shutupgcc1)(asar_error_id, int, const char*) = asar_error_template<errnull>; | ||
| 319 | void(*shutupgcc2)(asar_error_id, int, const char*) = asar_error_template<errblock>; | ||
| 320 | void(*shutupgcc3)(asar_error_id, int, const char*) = asar_error_template<errline>; | ||
| 321 | void(*shutupgcc4)(asar_error_id, int, const char*) = asar_error_template<errfatal>; | ||
| 322 | #endif | ||
| 323 | |||
| 324 | 218 | void asar_throw_error(int whichpass, asar_error_type type, asar_error_id errid, ...) | |
| 325 | { | ||
| 326 | 218 | assert(errid > error_id_start && errid < error_id_end); | |
| 327 | |||
| 328 | 218 | const asar_error_mapping& error = asar_errors[errid - error_id_start - 1]; | |
| 329 | |||
| 330 | 109 | char error_buffer[1024]; | |
| 331 | 109 | va_list args; | |
| 332 | 218 | va_start(args, errid); | |
| 333 | |||
| 334 | #if defined(__clang__) | ||
| 335 | # pragma clang diagnostic push | ||
| 336 | // "format string is not a literal". | ||
| 337 | // The pointer we're passing here should always point to a string literal, | ||
| 338 | // thus, I think, we can safely ignore this here. | ||
| 339 | # pragma clang diagnostic ignored "-Wformat-nonliteral" | ||
| 340 | #endif | ||
| 341 | |||
| 342 | 218 | vsnprintf(error_buffer, sizeof(error_buffer), error.message, args); | |
| 343 | |||
| 344 | #if defined(__clang__) | ||
| 345 | # pragma clang diagnostic pop | ||
| 346 | #endif | ||
| 347 | |||
| 348 | 218 | va_end(args); | |
| 349 | |||
| 350 | 218 | switch (type) | |
| 351 | { | ||
| 352 | 8 | case error_type_null: | |
| 353 | 8 | asar_error_template<errnull>(errid, whichpass, error_buffer); | |
| 354 | 8 | break; | |
| 355 | 188 | case error_type_block: | |
| 356 | 188 | asar_error_template<errblock>(errid, whichpass, error_buffer); | |
| 357 | ✗ | break; | |
| 358 | 18 | case error_type_line: | |
| 359 | 18 | asar_error_template<errline>(errid, whichpass, error_buffer); | |
| 360 | ✗ | break; | |
| 361 | 4 | case error_type_fatal: | |
| 362 | default: | ||
| 363 | 4 | asar_error_template<errfatal>(errid, whichpass, error_buffer); | |
| 364 | ✗ | break; | |
| 365 | } | ||
| 366 | 8 | } | |
| 367 | |||
| 368 | 94 | const char* get_error_name(asar_error_id errid) | |
| 369 | { | ||
| 370 | 94 | assert(errid > error_id_start && errid < error_id_end); | |
| 371 | |||
| 372 | 94 | const asar_error_mapping& error = asar_errors[errid - error_id_start - 1]; | |
| 373 | |||
| 374 | 94 | return error.name; | |
| 375 | } | ||
| 376 |