asar coverage - build #173


src/asar/
File: src/asar/warnings.cpp
Date: 2024-01-27 22:23:26
Lines:
67/68
98.5%
Functions:
9/9
100.0%
Branches:
40/52
76.9%

Line Branch Exec Source
1 #include "warnings.h"
2
3 #include "asar.h"
4 #include <cassert>
5 #include <cstdarg>
6
7 #include "interface-shared.h"
8
9 static int asar_num_warnings = 0;
10
11 struct asar_warning_mapping
12 {
13 asar_warning_id warnid;
14 const char* name;
15 const char* message;
16 bool enabled;
17 bool enabled_default;
18
19 2000 asar_warning_mapping(asar_warning_id inwarnid, const char *iname, const char* inmessage, bool inenabled = true)
20 2000 {
21 2000 ++asar_num_warnings;
22
23 2000 warnid = inwarnid;
24 2000 name = iname;
25 2000 message = inmessage;
26 2000 enabled = inenabled;
27 2000 enabled_default = inenabled;
28
29 // RPG Hacker: Sanity check. This makes sure that the order
30 // of entries in asar_warnings matches with the order of
31 // constants in asar_warning_id. This is important because
32 // we access asar_warnings as an array.
33 // Would love to do this via static_assert(), but can't
34 // think of a way to do so.
35
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2000 times.
2000 assert(warnid - warning_id_start == asar_num_warnings);
36 2000 }
37 };
38
39 // Keep in sync with asar_warning_id.
40 // Both, enum mapping and order, must match.
41 #define WRN(name) warning_id_ ## name, "W" #name
42 static asar_warning_mapping asar_warnings[] =
43 {
44 { WRN(relative_path_used), "Relative %s path passed to asar_patch_ex() - please use absolute paths only to prevent undefined behavior!" },
45
46 { WRN(rom_too_short), "ROM is too short to have a title. (Expected '%s')" },
47 { WRN(rom_title_incorrect), "ROM title is incorrect. Expected '%s', got '%s'." },
48
49 { WRN(spc700_assuming_8_bit), "This opcode does not exist with 16-bit parameters, assuming 8-bit." },
50 { WRN(assuming_address_mode), "The addressing mode %s is not valid for this instruction, assuming %s.%s" },
51
52 { WRN(set_middle_byte), "It would be wise to set the 008000 bit of this address." },
53
54 { WRN(freespace_leaked), "This freespace appears to be leaked." },
55
56 { WRN(warn_command), "warn command%s" },
57
58 { WRN(implicitly_sized_immediate), "Implicitly sized immediate.", false },
59
60 { WRN(check_memory_file), "Accessing file '%s' which is not in memory while W%d is enabled.", false },
61
62 { WRN(datasize_last_label), "Datasize used on last detected label '%s'." },
63 { WRN(datasize_exceeds_size), "Datasize exceeds 0xFFFF for label '%s'." },
64
65 { WRN(mapper_already_set), "A mapper has already been selected." },
66 { WRN(feature_deprecated), "DEPRECATION NOTIFICATION: Feature \"%s\" is deprecated and will be REMOVED in the future. Please update your code to conform to newer styles. Suggested work around: %s." },
67
68 { WRN(invalid_warning_id), "Warning '%s' (passed to %s) doesn't exist." },
69
70 { WRN(byte_order_mark_utf8), "UTF-8 byte order mark detected and skipped." },
71 };
72
73 // RPG Hacker: Sanity check. This makes sure that the element count of asar_warnings
74 // matches with the number of constants in asar_warning_id. This is important, because
75 // we are going to access asar_warnings as an array.
76 static_assert(sizeof(asar_warnings) / sizeof(asar_warnings[0]) == warning_id_count, "asar_warnings and asar_warning_id are not in sync");
77
78 2132 void asar_throw_warning(int whichpass, asar_warning_id warnid, ...)
79 {
80
2/2
✓ Branch 0 taken 1089 times.
✓ Branch 1 taken 1043 times.
2132 if (pass == whichpass)
81 {
82
2/4
✓ Branch 0 taken 547 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 547 times.
✗ Branch 3 not taken.
547 assert(warnid > warning_id_start && warnid < warning_id_end);
83
84 1089 const asar_warning_mapping& warning = asar_warnings[warnid - warning_id_start - 1];
85
86
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 967 times.
1089 if (warning.enabled)
87 {
88 char warning_buffer[1024];
89 va_list args;
90 122 va_start(args, warnid);
91
92 #if defined(__clang__)
93 # pragma clang diagnostic push
94 // "format string is not a literal".
95 // The pointer we're passing here should always point to a string literal,
96 // thus, I think, we can safely ignore this here.
97 # pragma clang diagnostic ignored "-Wformat-nonliteral"
98 #endif
99
100 122 vsnprintf(warning_buffer, sizeof(warning_buffer), warning.message, args);
101
102 #if defined(__clang__)
103 # pragma clang diagnostic pop
104 #endif
105
106 122 va_end(args);
107
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
122 warn((int)warnid, warning_buffer);
108 }
109 }
110 2132 }
111
112 204 const char* get_warning_name(asar_warning_id warnid)
113 {
114
2/4
✓ Branch 0 taken 104 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 104 times.
✗ Branch 3 not taken.
104 assert(warnid > warning_id_start && warnid < warning_id_end);
115
116 204 const asar_warning_mapping& warning = asar_warnings[warnid - warning_id_start - 1];
117
118 204 return warning.name;
119 }
120
121
122
123 200 void set_warning_enabled(asar_warning_id warnid, bool enabled)
124 {
125
2/4
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 101 times.
✗ Branch 3 not taken.
101 assert(warnid > warning_id_start && warnid < warning_id_end);
126
127 200 asar_warning_mapping& warning = asar_warnings[warnid - warning_id_start - 1];
128
129 200 warning.enabled = enabled;
130 200 }
131
132 254 asar_warning_id parse_warning_id_from_string(const char* string)
133 {
134 128 const char* pos = string;
135
136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 254 times.
254 if (pos == nullptr)
137 {
138 return warning_id_end;
139 }
140
141
142
3/4
✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 200 times.
✓ Branch 3 taken 54 times.
254 if (pos[0] == 'w' || pos[0] == 'W')
143 {
144 200 ++pos;
145 }
146
2/2
✓ Branch 0 taken 1709 times.
✓ Branch 1 taken 1692 times.
3401 for(int i = 0; i < warning_id_end-warning_id_start-1; i++)
147 {
148
2/2
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 3147 times.
3347 if(!stricmpwithlower(pos, asar_warnings[i].name+1))
149 {
150 200 return asar_warnings[i].warnid;
151 }
152 }
153
154 27 return warning_id_end;
155 }
156
157 508 void reset_warnings_to_default()
158 {
159
2/2
✓ Branch 0 taken 8128 times.
✓ Branch 1 taken 508 times.
8636 for (int i = (int)(warning_id_start + 1); i < (int)warning_id_end; ++i)
160 {
161 8128 asar_warning_mapping& warning = asar_warnings[i - (int)warning_id_start - 1];
162
163 8128 warning.enabled = warning.enabled_default;
164 }
165 508 }
166
167 struct warnings_state
168 {
169 bool enabled[warning_id_count];
170 };
171
172 static autoarray<warnings_state> warnings_state_stack;
173 static warnings_state main_warnings_state;
174
175 2253 void push_warnings(bool warnings_command)
176 {
177 warnings_state current_state;
178
179
2/2
✓ Branch 0 taken 36048 times.
✓ Branch 1 taken 2253 times.
38301 for (int i = 0; i < (int)warning_id_count; ++i)
180 {
181 36048 current_state.enabled[i] = asar_warnings[i].enabled;
182 }
183
184
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 2181 times.
2253 if (warnings_command)
185 {
186
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
72 warnings_state_stack.append(current_state);
187 }
188 else
189 {
190 2181 main_warnings_state = current_state;
191 }
192 2253 }
193
194 2223 void pull_warnings(bool warnings_command)
195 {
196
4/4
✓ Branch 0 taken 2169 times.
✓ Branch 1 taken 54 times.
✓ Branch 2 taken 2151 times.
✓ Branch 3 taken 18 times.
2223 if (warnings_state_stack.count > 0 || !warnings_command)
197 {
198 warnings_state prev_state;
199
200
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 1107 times.
1161 if (warnings_command)
201 {
202
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
54 prev_state = warnings_state_stack[warnings_state_stack.count - 1];
203 }
204 else
205 {
206 2151 prev_state = main_warnings_state;
207 }
208
209
2/2
✓ Branch 0 taken 35280 times.
✓ Branch 1 taken 2205 times.
37485 for (int i = 0; i < (int)warning_id_count; ++i)
210 {
211 35280 asar_warnings[i].enabled = prev_state.enabled[i];
212 }
213
214
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 2151 times.
2205 if (warnings_command)
215 {
216 54 warnings_state_stack.remove(warnings_state_stack.count - 1);
217 }
218 2205 }
219 else
220 {
221 18 asar_throw_error(0, error_type_block, error_id_pullwarnings_without_pushwarnings);
222 }
223 2205 }
224
225 2151 void verify_warnings()
226 {
227
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 2133 times.
2151 if (warnings_state_stack.count > 0)
228 {
229 18 asar_throw_error(0, error_type_null, error_id_pushwarnings_without_pullwarnings);
230
231 18 warnings_state_stack.reset();
232 }
233 2151 }
234