asar coverage - build #72


src/asar/
File: src/asar/warnings.cpp
Date: 2024-01-18 08:25:45
Lines:
62/68
91.2%
Functions:
8/9
88.9%
Branches:
39/54
72.2%

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 3658 asar_warning_mapping(asar_warning_id inwarnid, const char *iname, const char* inmessage, bool inenabled = true)
20 3658 {
21 3658 ++asar_num_warnings;
22
23 3658 warnid = inwarnid;
24 3658 name = iname;
25 3658 message = inmessage;
26 3658 enabled = inenabled;
27 3658 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 3658 times.
3658 assert(warnid - warning_id_start == asar_num_warnings);
36 3658 }
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(65816_yy_x_does_not_exist), "($yy),x does not exist, assuming $yy,x." },
50 { WRN(65816_xx_y_assume_16_bit), "%s $xx,y is not valid with 8-bit parameters, assuming 16-bit." },
51 { WRN(spc700_assuming_8_bit), "This opcode does not exist with 16-bit parameters, assuming 8-bit." },
52
53 { WRN(cross_platform_path), "This patch may not assemble cleanly on all platforms. Please use / instead." },
54
55 { WRN(missing_org), "Missing org or freespace command." },
56 { WRN(set_middle_byte), "It would be wise to set the 008000 bit of this address." },
57
58 { WRN(unrecognized_special_command), "Unrecognized special command - your version of Asar might be outdated." },
59
60 { WRN(freespace_leaked), "This freespace appears to be leaked." },
61
62 { WRN(warn_command), "warn command%s" },
63
64 { WRN(implicitly_sized_immediate), "Implicitly sized immediate.", false },
65
66 { WRN(xkas_deprecated), "xkas support is being deprecated and will be removed in a future version of Asar. Please use an older version of Asar (<=1.50) if you need it." },
67 { WRN(xkas_eat_parentheses), "xkas compatibility warning: Unlike xkas, Asar does not eat parentheses after defines." },
68 { WRN(xkas_label_access), "xkas compatibility warning: Label access is always 24bit in emulation mode, but may be 16bit in native mode." },
69 { WRN(xkas_warnpc_relaxed), "xkas conversion warning : warnpc is relaxed one byte in Asar." },
70 { WRN(xkas_style_conditional), "xkas-style conditional compilation detected. Please use the if command instead." },
71 { WRN(xkas_patch), "If you want to assemble an xkas patch, add ;@xkas at the top or you may run into a couple of problems." },
72 { WRN(xkas_incsrc_relative), "xkas compatibility warning: incsrc and incbin look for files relative to the patch in Asar, but xkas looks relative to the assembler." },
73 { WRN(convert_to_asar), "Convert the patch to native Asar format instead of making an Asar-only xkas patch." },
74
75 { WRN(fixed_deprecated), "the 'fixed' parameter on freespace/freecode/freedata is deprecated - please use 'static' instead." },
76
77 { WRN(autoclear_deprecated), "'autoclear' is deprecated - please use 'autoclean' instead." },
78
79 { WRN(check_memory_file), "Accessing file '%s' which is not in memory while W%d is enabled.", false },
80
81 { WRN(if_not_condition_deprecated), "'if !condition' is deprecated - please use 'if not(condition)' instead." },
82
83 { WRN(function_redefined), "Function '%s' redefined." },
84
85 { WRN(datasize_last_label), "Datasize used on last detected label '%s'." },
86 { WRN(datasize_exceeds_size), "Datasize exceeds 0xFFFF for label '%s'." },
87
88 { WRN(mapper_already_set), "A mapper has already been selected." },
89 { 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." },
90
91 { WRN(byte_order_mark_utf8), "UTF-8 byte order mark detected and skipped." },
92 };
93
94 // RPG Hacker: Sanity check. This makes sure that the element count of asar_warnings
95 // matches with the number of constants in asar_warning_id. This is important, because
96 // we are going to access asar_warnings as an array.
97 static_assert(sizeof(asar_warnings) / sizeof(asar_warnings[0]) == warning_id_count, "asar_warnings and asar_warning_id are not in sync");
98
99 714 void asar_throw_warning(int whichpass, asar_warning_id warnid, ...)
100 {
101
2/2
✓ Branch 0 taken 362 times.
✓ Branch 1 taken 352 times.
714 if (pass == whichpass)
102 {
103
2/4
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 181 times.
181 assert(warnid > warning_id_start && warnid < warning_id_end);
104
105 362 const asar_warning_mapping& warning = asar_warnings[warnid - warning_id_start - 1];
106
107
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 328 times.
362 if (warning.enabled)
108 {
109 char warning_buffer[1024];
110 va_list args;
111 34 va_start(args, warnid);
112
113 #if defined(__clang__)
114 # pragma clang diagnostic push
115 // "format string is not a literal".
116 // The pointer we're passing here should always point to a string literal,
117 // thus, I think, we can safely ignore this here.
118 # pragma clang diagnostic ignored "-Wformat-nonliteral"
119 #endif
120
121
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
34 vsnprintf(warning_buffer, sizeof(warning_buffer), warning.message, args);
122
123 #if defined(__clang__)
124 # pragma clang diagnostic pop
125 #endif
126
127 34 va_end(args);
128
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
34 warn((int)warnid, warning_buffer);
129 }
130 }
131 714 }
132
133 34 const char* get_warning_name(asar_warning_id warnid)
134 {
135
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
17 assert(warnid > warning_id_start && warnid < warning_id_end);
136
137 34 const asar_warning_mapping& warning = asar_warnings[warnid - warning_id_start - 1];
138
139 34 return warning.name;
140 }
141
142
143
144 66 void set_warning_enabled(asar_warning_id warnid, bool enabled)
145 {
146
2/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 33 times.
33 assert(warnid > warning_id_start && warnid < warning_id_end);
147
148 66 asar_warning_mapping& warning = asar_warnings[warnid - warning_id_start - 1];
149
150 66 warning.enabled = enabled;
151 66 }
152
153 84 asar_warning_id parse_warning_id_from_string(const char* string)
154 {
155 42 const char* pos = string;
156
157
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (pos == nullptr)
158 {
159 return warning_id_end;
160 }
161
162
163
3/4
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
✓ Branch 3 taken 18 times.
84 if (pos[0] == 'w' || pos[0] == 'W')
164 {
165 66 ++pos;
166 }
167
2/2
✓ Branch 0 taken 1143 times.
✓ Branch 1 taken 1143 times.
2286 for(int i = 0; i < warning_id_end-warning_id_start-1; i++)
168 {
169
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 2202 times.
2268 if(!stricmpwithlower(pos, asar_warnings[i].name+1))
170 {
171 66 return asar_warnings[i].warnid;
172 }
173 }
174
175 9 return warning_id_end;
176 }
177
178 void reset_warnings_to_default()
179 {
180 for (int i = (int)(warning_id_start + 1); i < (int)warning_id_end; ++i)
181 {
182 asar_warning_mapping& warning = asar_warnings[i - (int)warning_id_start - 1];
183
184 warning.enabled = warning.enabled_default;
185 }
186 }
187
188 struct warnings_state
189 {
190 bool enabled[warning_id_count];
191 };
192
193 static autoarray<warnings_state> warnings_state_stack;
194 static warnings_state main_warnings_state;
195
196 712 void push_warnings(bool warnings_command)
197 {
198 warnings_state current_state;
199
200
2/2
✓ Branch 0 taken 22072 times.
✓ Branch 1 taken 712 times.
22784 for (int i = 0; i < (int)warning_id_count; ++i)
201 {
202 22072 current_state.enabled[i] = asar_warnings[i].enabled;
203 }
204
205
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 688 times.
712 if (warnings_command)
206 {
207
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
24 warnings_state_stack.append(current_state);
208 }
209 else
210 {
211 688 main_warnings_state = current_state;
212 }
213 712 }
214
215 702 void pull_warnings(bool warnings_command)
216 {
217
4/4
✓ Branch 0 taken 684 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 678 times.
✓ Branch 3 taken 6 times.
702 if (warnings_state_stack.count > 0 || !warnings_command)
218 {
219 warnings_state prev_state;
220
221
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 339 times.
357 if (warnings_command)
222 {
223
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
18 prev_state = warnings_state_stack[warnings_state_stack.count - 1];
224 }
225 else
226 {
227 678 prev_state = main_warnings_state;
228 }
229
230
2/2
✓ Branch 0 taken 21576 times.
✓ Branch 1 taken 696 times.
22272 for (int i = 0; i < (int)warning_id_count; ++i)
231 {
232 21576 asar_warnings[i].enabled = prev_state.enabled[i];
233 }
234
235
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 678 times.
696 if (warnings_command)
236 {
237 18 warnings_state_stack.remove(warnings_state_stack.count - 1);
238 }
239 696 }
240 else
241 {
242 6 asar_throw_error(0, error_type_block, error_id_pullwarnings_without_pushwarnings);
243 }
244 696 }
245
246 678 void verify_warnings()
247 {
248
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 672 times.
678 if (warnings_state_stack.count > 0)
249 {
250 6 asar_throw_error(0, error_type_null, error_id_pushwarnings_without_pullwarnings);
251
252 6 warnings_state_stack.reset();
253 }
254 678 }
255