| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #define ALL_ERRORS(ERR) \ | ||
| 4 | ERR(limit_reached, "Over %d errors detected. Aborting.") \ | ||
| 5 | ERR(werror, "One or more warnings was detected with werror on.") \ | ||
| 6 | ERR(buffer_too_small, "The given buffer is too small to contain the resulting ROM.") \ | ||
| 7 | ERR(params_null, "params passed to asar_patch_ex() is null.") \ | ||
| 8 | ERR(params_invalid_size, "Size of params passed to asar_patch_ex() is invalid.") \ | ||
| 9 | ERR(cmdl_define_invalid, "Invalid define name in %s: '%s'.") \ | ||
| 10 | ERR(cmdl_define_override, "%s '%s' overrides a previous define. Did you specify the same define twice?") \ | ||
| 11 | ERR(create_rom_failed, "Couldn't create ROM.") \ | ||
| 12 | ERR(open_rom_failed, "Couldn't open ROM.") \ | ||
| 13 | ERR(open_rom_not_smw_extension, "Doesn't look like an SMW ROM. (Maybe its extension is wrong?)") \ | ||
| 14 | ERR(open_rom_not_smw_header, "Doesn't look like an SMW ROM. (Maybe it's headered?)") \ | ||
| 15 | ERR(stddefines_no_identifier, "stddefines.txt contains a line with a value, but no identifier.") \ | ||
| 16 | ERR(stddefine_after_closing_quote, "Broken std defines. (Something after closing quote)") \ | ||
| 17 | ERR(failed_to_open_file, "Failed to open file '%s'.") \ | ||
| 18 | ERR(file_not_found, "File '%s' wasn't found.") \ | ||
| 19 | ERR(file_offset_out_of_bounds, "File offset %s out of bounds for file '%s'.") \ | ||
| 20 | ERR(mismatched_parentheses, "Mismatched parentheses.") \ | ||
| 21 | ERR(invalid_hex_value, "Invalid hex value.") \ | ||
| 22 | ERR(invalid_binary_value, "Invalid binary value.") \ | ||
| 23 | ERR(invalid_character, "Invalid character.") \ | ||
| 24 | ERR(string_literal_not_terminated, "String literal not terminated.") \ | ||
| 25 | ERR(malformed_function_call, "Malformed function call.") \ | ||
| 26 | ERR(invalid_number, "Invalid number.") \ | ||
| 27 | ERR(garbage_near_quoted_string, "Garbage near quoted string.") \ | ||
| 28 | ERR(mismatched_quotes, "Mismatched quotes.") \ | ||
| 29 | ERR(rom_too_short, "ROM is too short to have a title. (Expected '%s')") \ | ||
| 30 | ERR(rom_title_incorrect, "ROM title is incorrect. Expected '%s', got '%s'.") \ | ||
| 31 | ERR(bank_border_crossed, "A bank border was crossed, SNES address $%06X.") \ | ||
| 32 | ERR(start_of_file, "This command may only be used at the start of a file.") \ | ||
| 33 | ERR(invalid_version_number, "Invalid version number.") \ | ||
| 34 | ERR(asar_too_old, "This version of Asar is too old for this patch.") \ | ||
| 35 | ERR(relative_branch_out_of_bounds, "Relative branch out of bounds. (Distance is %s).") \ | ||
| 36 | ERR(snes_address_doesnt_map_to_rom, "SNES address %s doesn't map to ROM.") \ | ||
| 37 | ERR(snes_address_out_of_bounds, "SNES address %s out of bounds.") \ | ||
| 38 | ERR(invalid_tcall, "Invalid tcall.") \ | ||
| 39 | ERR(use_xplus, "Use (x+) instead.") \ | ||
| 40 | ERR(opcode_length_too_long, "Opcode length is too long.") \ | ||
| 41 | ERR(superfx_invalid_short_address, "Invalid short address parameter: $%s. (Must be even number and $0000-$01FE)") \ | ||
| 42 | ERR(superfx_invalid_register, "Invalid register for opcode; valid range is %d-%d.") \ | ||
| 43 | ERR(invalid_opcode_length, "Invalid opcode length specification.") \ | ||
| 44 | ERR(invalid_mapper, "Invalid mapper.") \ | ||
| 45 | ERR(nan, "NaN encountered.") \ | ||
| 46 | ERR(division_by_zero, "Division by zero.") \ | ||
| 47 | ERR(modulo_by_zero, "Modulo by zero.") \ | ||
| 48 | ERR(unknown_operator, "Unknown operator.") \ | ||
| 49 | ERR(invalid_input, "Invalid input.") \ | ||
| 50 | ERR(invalid_function_name, "Invalid function name.") \ | ||
| 51 | ERR(function_not_found, "Function '%s' wasn't found.") \ | ||
| 52 | ERR(function_redefined, "Function '%s' redefined.") \ | ||
| 53 | ERR(broken_function_declaration, "Broken function declaration.") \ | ||
| 54 | ERR(wrong_num_parameters, "Wrong number of parameters to function.") \ | ||
| 55 | ERR(invalid_param_name, "Invalid parameter name '%s'.") \ | ||
| 56 | ERR(invalid_label_name, "Invalid label name.") \ | ||
| 57 | ERR(label_not_found, "Label '%s' wasn't found.") \ | ||
| 58 | ERR(label_redefined, "Label '%s' redefined.") \ | ||
| 59 | ERR(broken_label_definition, "Broken label definition.") \ | ||
| 60 | ERR(macro_label_outside_of_macro, "Macro label outside of a macro.") \ | ||
| 61 | ERR(invalid_namespace_name, "Invalid namespace name.") \ | ||
| 62 | ERR(invalid_namespace_use, "Invalid use of namespace command.") \ | ||
| 63 | ERR(invalid_struct_name, "Invalid struct name.") \ | ||
| 64 | ERR(struct_not_found, "Struct '%s' wasn't found.") \ | ||
| 65 | ERR(struct_redefined, "Struct '%s' redefined.") \ | ||
| 66 | ERR(struct_invalid_parent_name, "Invalid parent name.") \ | ||
| 67 | ERR(invalid_label_missing_closer, "Invalid label name, missing array closer.") \ | ||
| 68 | ERR(invalid_subscript, "Invalid array subscript after first scope resolution.") \ | ||
| 69 | ERR(label_missing_parent, "This label has no parent.") \ | ||
| 70 | ERR(struct_without_endstruct, "struct without matching endstruct.") \ | ||
| 71 | ERR(nested_struct, "Can not nest structs.") \ | ||
| 72 | ERR(missing_struct_params, "Missing struct parameters.") \ | ||
| 73 | ERR(too_many_struct_params, "Too many struct parameters.") \ | ||
| 74 | ERR(missing_extends, "Missing extends keyword.") \ | ||
| 75 | ERR(invalid_endstruct_count, "Invalid endstruct parameter count.") \ | ||
| 76 | ERR(expected_align, "Expected align parameter.") \ | ||
| 77 | ERR(endstruct_without_struct, "endstruct can only be used in combination with struct.") \ | ||
| 78 | ERR(alignment_too_small, "Alignment must be >= 1.") \ | ||
| 79 | ERR(invalid_define_name, "Invalid define name.") \ | ||
| 80 | ERR(define_not_found, "Define '%s' wasn't found.") \ | ||
| 81 | ERR(broken_define_declaration, "Broken define declaration.") \ | ||
| 82 | ERR(overriding_builtin_define, "Trying to set define '%s', which is the name of a built-in define and thus can't be modified.") \ | ||
| 83 | ERR(define_label_math, "!Define #= Label is not allowed with non-static labels.") \ | ||
| 84 | ERR(mismatched_braces, "Mismatched braces.") \ | ||
| 85 | ERR(invalid_macro_name, "Invalid macro name.") \ | ||
| 86 | ERR(macro_not_found, "Macro '%s' wasn't found.") \ | ||
| 87 | ERR(macro_redefined, "Macro '%s' redefined. First defined at: %s:%d") \ | ||
| 88 | ERR(broken_macro_declaration, "Broken macro declaration.") \ | ||
| 89 | ERR(invalid_macro_param_name, "Invalid macro parameter name.") \ | ||
| 90 | ERR(macro_param_not_found, "Macro parameter '%s' wasn't found.%s") \ | ||
| 91 | ERR(macro_param_redefined, "Macro parameter '%s' redefined") \ | ||
| 92 | ERR(broken_macro_usage, "Broken macro usage.") \ | ||
| 93 | ERR(macro_wrong_num_params, "Wrong number of parameters to macro.") \ | ||
| 94 | ERR(misplaced_endmacro, "Misplaced endmacro.") \ | ||
| 95 | ERR(unclosed_macro, "Unclosed macro: '%s'.") \ | ||
| 96 | ERR(label_in_conditional, "Non-static label in %s command.") \ | ||
| 97 | ERR(misplaced_elseif, "Misplaced elseif.") \ | ||
| 98 | ERR(elseif_in_while, "Can't use elseif in a while loop.") \ | ||
| 99 | ERR(misplaced_endif, "Misplaced endif.") \ | ||
| 100 | ERR(misplaced_else, "Misplaced else.") \ | ||
| 101 | ERR(else_in_while_loop, "Can't use else in a while loop.") \ | ||
| 102 | ERR(unclosed_if, "Unclosed if statement.") \ | ||
| 103 | ERR(unknown_command, "Unknown command.") \ | ||
| 104 | ERR(broken_incbin, "Broken incbin command.") \ | ||
| 105 | ERR(recursion_limit, "Recursion limit reached.") \ | ||
| 106 | ERR(cant_be_main_file, "This file may not be used as the main file.%s") \ | ||
| 107 | ERR(no_labels_here, "Can't use non-static labels here.") \ | ||
| 108 | ERR(invalid_freespace_request, "Invalid freespace request.") \ | ||
| 109 | ERR(static_freespace_autoclean, "A static freespace must be targeted by at least one autoclean.") \ | ||
| 110 | ERR(static_freespace_growing, "A static freespace may not grow.") \ | ||
| 111 | ERR(no_freespace_in_mapped_banks, "No freespace found in the mapped banks. (Requested size: %s)") \ | ||
| 112 | ERR(no_freespace, "No freespace found. (Requested size: %s)") \ | ||
| 113 | ERR(prot_not_at_freespace_start, "PROT must be used at the start of a freespace block.") \ | ||
| 114 | ERR(prot_too_many_entries, "Too many entries to PROT.") \ | ||
| 115 | ERR(autoclean_in_freespace, "autoclean used in freespace.") \ | ||
| 116 | 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.") \ | ||
| 117 | ERR(broken_autoclean, "Broken autoclean command.") \ | ||
| 118 | ERR(pulltable_without_table, "Using pulltable when there is no table on the stack yet.") \ | ||
| 119 | ERR(pad_in_freespace, "pad does not make sense in a freespaced code.") \ | ||
| 120 | ERR(base_label_invalid, "base Label is not valid.") \ | ||
| 121 | ERR(pushpc_without_pullpc, "pushpc without matching pullpc.") \ | ||
| 122 | ERR(pullpc_without_pushpc, "pullpc without matching pushpc.") \ | ||
| 123 | ERR(pullpc_different_arch, "pullpc in another architecture than the pushpc.") \ | ||
| 124 | ERR(pullbase_without_pushbase, "pullbase without matching pushbase.") \ | ||
| 125 | ERR(invalid_check, "Invalid check command.") \ | ||
| 126 | ERR(assertion_failed, "Assertion failed%s") \ | ||
| 127 | ERR(error_command, "error command%s") \ | ||
| 128 | ERR(invalid_print_function_syntax, "Invalid printable string syntax.") \ | ||
| 129 | ERR(unknown_variable, "Unknown variable.") \ | ||
| 130 | ERR(pushwarnings_without_pullwarnings, "warnings push without matching warnings pull.") \ | ||
| 131 | ERR(pullwarnings_without_pushwarnings, "warnings pull without matching warnings push.") \ | ||
| 132 | ERR(failed_to_open_file_access_denied, "Failed to open file '%s'. Access denied.") \ | ||
| 133 | ERR(failed_to_open_not_regular_file, "Failed to open file '%s'. Not a regular file (did you try to use a directory?)") \ | ||
| 134 | ERR(bad_dp_base, "The dp base should be page aligned (i.e. a multiple of 256), got %s") \ | ||
| 135 | ERR(bad_dp_optimize, "Bad dp optimize value %s, expected: [none, ram, always]") \ | ||
| 136 | ERR(bad_address_optimize, "Bad dp optimize value %s, expected: [default, ram, mirrors]") \ | ||
| 137 | ERR(bad_optimize, "Bad optimize value %s, expected: [dp, address]") \ | ||
| 138 | ERR(require_parameter, "Missing required function parameter") \ | ||
| 139 | ERR(expected_parameter, "Not enough parameters in calling of function %s") \ | ||
| 140 | ERR(unexpected_parameter, "Too many parameters in calling of function %s") \ | ||
| 141 | ERR(duplicate_param_name, "Duplicated parameter name: %s in creation of function %s") \ | ||
| 142 | ERR(invalid_alignment, "Invalid alignment. Expected a power of 2.") \ | ||
| 143 | ERR(alignment_too_big, "Requested alignment too large.") \ | ||
| 144 | ERR(negative_shift, "Bitshift amount is negative.") \ | ||
| 145 | ERR(macro_not_varadic, "Invalid use of %s, active macro is not variadic.") \ | ||
| 146 | ERR(vararg_sizeof_nomacro, "Invalid use of sizeof(...), no active macro.") \ | ||
| 147 | ERR(macro_wrong_min_params, "Variadic macro call with too few parameters") \ | ||
| 148 | ERR(vararg_out_of_bounds, "Variadic macro parameter %s is out of bounds.%s") \ | ||
| 149 | ERR(vararg_must_be_last, "Variadic macro parameter must be the last parameter.") \ | ||
| 150 | ERR(invalid_global_label, "Global label definition contains an invalid label [%s].") \ | ||
| 151 | ERR(spc700_addr_out_of_range, "Address %s out of range for instruction, valid range is 0000-1FFF") \ | ||
| 152 | ERR(label_ambiguous, "Label (%s) location is ambiguous due to straddling optimization border.") \ | ||
| 153 | ERR(feature_unavaliable_in_spcblock, "This feature may not be used while an spcblock is active") \ | ||
| 154 | ERR(endspcblock_without_spcblock, "Use of endspcblock without matching spcblock") \ | ||
| 155 | ERR(missing_endspcblock, "Use of endspcblock without matching spcblock") \ | ||
| 156 | ERR(spcblock_inside_struct, "Can not start an spcblock while a struct is still open") \ | ||
| 157 | ERR(spcblock_too_few_args, "Too few args passed to spcblock") \ | ||
| 158 | ERR(spcblock_too_many_args, "Too many args passed to spcblock") \ | ||
| 159 | ERR(unknown_spcblock_type, "Unknown spcblock format") \ | ||
| 160 | ERR(custom_spcblock_missing_macro, "Custom spcblock types must refer to a valid macro") \ | ||
| 161 | ERR(spcblock_macro_doesnt_exist, "Macro specified to custom spcblock was not found") \ | ||
| 162 | ERR(extra_spcblock_arg_for_type, "Only custom spcblock type takes a fourth argument") \ | ||
| 163 | ERR(spcblock_macro_must_be_varadic, "Custom spcblock macros must be variadic") \ | ||
| 164 | ERR(spcblock_macro_invalid_static_args, "Custom spcblock macros must have three static arguments") \ | ||
| 165 | ERR(spcblock_custom_types_incomplete, "Custom spcblock types are not yet supported. One day.") \ | ||
| 166 | ERR(invalid_endspcblock_arg, "Invalid argument to endspcblock: \"%s\"") \ | ||
| 167 | ERR(unknown_endspcblock_format, "Unsupported endspcblock format. Currently supported formats are \"endspcblock\" and \"endspcblock execute [label]\"") \ | ||
| 168 | ERR(internal_error, "An internal error occured (%s). This is a bug in Asar, please report it at https://github.com/RPGHacker/asar/issues, along with a patch that reproduces it if possible.") \ | ||
| 169 | ERR(pushns_without_pullns, "pushns without matching pullns.") \ | ||
| 170 | ERR(pullns_without_pushns, "pullns without matching pushns.") \ | ||
| 171 | ERR(label_forward, "The use of forward labels is not allowed in this context.") \ | ||
| 172 | ERR(undefined_char, "'%s' is not defined in the character table") \ | ||
| 173 | ERR(invalid_utf8, "Invalid text encoding detected. Asar expects UTF-8-encoded text. Please re-save this file in a text editor of choice using UTF-8 encoding.") \ | ||
| 174 | ERR(cmdl_utf16_to_utf8_failed, "UTF-16 to UTF-8 string conversion failed: %s.") \ | ||
| 175 | ERR(broken_command, "Broken %s command. %s") \ | ||
| 176 | ERR(oob, "Operation out of bounds: Requested index %d for object of size %d") \ | ||
| 177 | ERR(unclosed_vararg, "Variadic macro parameter wasn't closed properly.") \ | ||
| 178 | ERR(invalid_vararg, "Trying to use variadic macro parameter syntax to resolve a non variadic argument <%s>.") \ | ||
| 179 | ERR(invalid_depth_resolve, "Invalid %s resolution depth: Trying to backwards-resolve a %s using %i '^', but current scope only supports up to %i '^'.") \ | ||
| 180 | ERR(platform_paths, "Platform-specific paths aren'supported. Please use platform-independent paths (use / instead of \\).") \ | ||
| 181 | ERR(bad_single_line_for, "Single-line for loop not allowed here.") \ | ||
| 182 | ERR(broken_for_loop, "Broken for loop command: %s") \ | ||
| 183 | ERR(missing_org, "Missing org or freespace command.") \ | ||
| 184 | ERR(unclosed_block_comment, "Unclosed block comment.") \ | ||
| 185 | ERR(bad_addr_mode, "This addressing mode is not valid for this instruction.") \ | ||
| 186 | ERR(bad_access_width, "This addressing mode can accept %s arguments, but the provided argument is %d-bit.") \ | ||
| 187 | ERR(label_before_if, "Labels are not allowed before \"%s\" commands. Suggestion: move the label to a separate line.") \ | ||
| 188 | ERR(expected_number, "Expected number, got string instead") \ | ||
| 189 | ERR(expected_string, "Expected string, got number instead") \ | ||
| 190 | ERR(expected_ident, "Expected identifier") \ | ||
| 191 | ERR(argument_count, "Wrong number of arguments. Expected %d, got %d") \ | ||
| 192 | // this line intentionally left blank | ||
| 193 | |||
| 194 | enum asar_error_id : int { | ||
| 195 | #define DO(id, fmt) error_id_ ## id, | ||
| 196 | ALL_ERRORS(DO) | ||
| 197 | #undef DO | ||
| 198 | error_id_end, | ||
| 199 | }; | ||
| 200 | |||
| 201 | struct asar_error_mapping { | ||
| 202 | const char* name; | ||
| 203 | const char* fmt_string; | ||
| 204 | }; | ||
| 205 | |||
| 206 | inline constexpr asar_error_mapping asar_all_errors[] = { | ||
| 207 | #define DO(id, fmt) { "E" #id, fmt }, | ||
| 208 | ALL_ERRORS(DO) | ||
| 209 | #undef DO | ||
| 210 | }; | ||
| 211 | |||
| 212 | 541 | constexpr const char* get_error_fmt(asar_error_id errid) { | |
| 213 | 541 | return asar_all_errors[errid].fmt_string; | |
| 214 | } | ||
| 215 | |||
| 216 | enum asar_error_type | ||
| 217 | { | ||
| 218 | error_type_fatal, | ||
| 219 | error_type_line, | ||
| 220 | error_type_block, | ||
| 221 | error_type_null | ||
| 222 | }; | ||
| 223 | |||
| 224 | struct errfatal {}; | ||
| 225 | struct errline : public errfatal {}; | ||
| 226 | struct errblock : public errline {}; | ||
| 227 | struct errnull : public errblock {}; | ||
| 228 | |||
| 229 | #ifdef __clang__ | ||
| 230 | // okay so this ## thing isn't very nice of me, but it works on all compilers | ||
| 231 | // for now. i'll refactor all use sites of asar_throw_error at some point so i | ||
| 232 | // can do a different hack to always pass at least 1 variadic argument | ||
| 233 | //edit: lol nevermind, different hack didn't work either, guess we're stuck | ||
| 234 | // with this shit until we upgrade to c++20 | ||
| 235 | #pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" | ||
| 236 | #endif | ||
| 237 | #if defined(__clang__) || defined(__GNUC__) | ||
| 238 | #define FORMAT [[gnu::format(printf, 3, 4)]] | ||
| 239 | #else | ||
| 240 | // msvc only has format string checking in enterprise edition lmao | ||
| 241 | // ehh who tf even develops on windows anyways | ||
| 242 | #define FORMAT | ||
| 243 | #endif | ||
| 244 | |||
| 245 | // "Magic Trick" to get noreturn on all but the null throw functions: use | ||
| 246 | // preprocessor macros as makeshift template specializations | ||
| 247 | |||
| 248 | // i would do this with explicit template specializations, but there's a 6 year | ||
| 249 | // old open Clang bug report about [[noreturn]] not working with function | ||
| 250 | // specializations. | ||
| 251 | |||
| 252 | FORMAT void asar_throw_error_impl_error_type_null(int whichpass, asar_error_id errid, const char* fmt, ...); | ||
| 253 | FORMAT [[noreturn]] void asar_throw_error_impl_error_type_block(int whichpass, asar_error_id errid, const char* fmt, ...); | ||
| 254 | FORMAT [[noreturn]] void asar_throw_error_impl_error_type_line(int whichpass, asar_error_id errid, const char* fmt, ...); | ||
| 255 | FORMAT [[noreturn]] void asar_throw_error_impl_error_type_fatal(int whichpass, asar_error_id errid, const char* fmt, ...); | ||
| 256 | #undef FORMAT | ||
| 257 | #define asar_throw_error(whichpass, type, errid, ...) asar_throw_error_impl_ ## type(whichpass, errid, get_error_fmt(errid), ## __VA_ARGS__) | ||
| 258 | const char* get_error_name(asar_error_id errid); | ||
| 259 |