asar coverage - build #199


src/asar/
File: src/asar/interface-lib.cpp
Date: 2024-02-01 13:53:00
Lines:
258/276
93.5%
Functions:
29/30
96.7%
Branches:
159/272
58.5%

Line Branch Exec Source
1 #include "asar.h"
2 #include "crc32.h"
3 #include "virtualfile.h"
4 #include "platform/file-helpers.h"
5 #include "interface-shared.h"
6 #include "assembleblock.h"
7 #include "asar_math.h"
8 #include "platform/thread-helpers.h"
9
10 #if defined(CPPCLI)
11 #define EXPORT extern "C"
12 #elif defined(_WIN32)
13 #ifdef ASAR_SHARED
14 #define EXPORT extern "C" __declspec(dllexport)
15 #elif defined(ASAR_STATIC)
16 #define EXPORT extern "C"
17 #endif
18 #else
19 #define EXPORT extern "C" __attribute__ ((visibility ("default")))
20 #endif
21
22 static autoarray<const char *> prints;
23 static string symbolsfile;
24 static int numprint;
25 static uint32_t romCrc;
26
27 #define APIVERSION 400
28
29 // note: somewhat fragile, assumes that every patchparams struct inherits from exactly the previous one
30 /* $EXPORTSTRUCT_PP$
31 */
32 struct patchparams_base {
33 // The size of this struct. Set to (int)sizeof(patchparams).
34 int structsize;
35 };
36
37
38 /* $EXPORTSTRUCT$
39 */
40 struct stackentry {
41 const char * fullpath;
42 const char * prettypath;
43 int lineno;
44 const char * details;
45 };
46
47 /* $EXPORTSTRUCT$
48 */
49 struct errordata {
50 const char * fullerrdata;
51 const char * rawerrdata;
52 const char * block;
53 const char * filename;
54 int line;
55 const struct stackentry * callstack;
56 int callstacksize;
57 const char * errname;
58 };
59 static autoarray<errordata> errors;
60 static int numerror;
61
62 static autoarray<errordata> warnings;
63 static int numwarn;
64
65 /* $EXPORTSTRUCT$
66 */
67 struct labeldata {
68 const char * name;
69 int location;
70 };
71
72 /* $EXPORTSTRUCT$
73 */
74 struct definedata {
75 const char * name;
76 const char * contents;
77 };
78
79 /* $EXPORTSTRUCT$
80 */
81 struct warnsetting {
82 const char * warnid;
83 bool enabled;
84 };
85
86 /* $EXPORTSTRUCT$
87 */
88 struct memoryfile {
89 const char* path;
90 const void* buffer;
91 size_t length;
92 };
93
94 190 void print(const char * str)
95 {
96 190 prints[numprint++]= duplicate_string(str);
97 190 }
98
99 466 static void fillerror(errordata& myerr, const char* errname, const char * type, const char * str, bool show_block)
100 {
101
1/2
✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
466 const char* current_filename = get_current_file_name();
102
2/2
✓ Branch 0 taken 465 times.
✓ Branch 1 taken 1 times.
466 if(current_filename) myerr.filename= duplicate_string(current_filename);
103 1 else myerr.filename = duplicate_string("");
104
1/2
✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
466 myerr.line=get_current_line();
105
1/2
✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
466 const char* current_block = get_current_block();
106
2/2
✓ Branch 0 taken 445 times.
✓ Branch 1 taken 21 times.
466 if (current_block) myerr.block= duplicate_string(current_block);
107 21 else myerr.block= duplicate_string("");
108 466 myerr.rawerrdata= duplicate_string(str);
109 236 string location;
110 236 string details;
111
1/2
✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
466 get_current_line_details(&location, &details);
112
6/12
✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 236 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 236 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 236 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 236 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 236 times.
✗ Branch 11 not taken.
696 myerr.fullerrdata= duplicate_string(location+": "+type+str+details+get_callstack());
113 466 myerr.errname = duplicate_string(errname);
114
115 236 autoarray<printable_callstack_entry> printable_stack;
116
1/2
✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
466 get_full_printable_callstack(&printable_stack, 0, false);
117
118 466 myerr.callstacksize = printable_stack.count;
119 466 myerr.callstack = static_cast<stackentry*>(malloc(sizeof(stackentry) * myerr.callstacksize));
120
121
2/2
✓ Branch 0 taken 15818 times.
✓ Branch 1 taken 466 times.
16284 for (int i = 0; i < myerr.callstacksize; ++i)
122 {
123 15818 stackentry& entry = const_cast<stackentry&>(myerr.callstack[i]);
124
125
1/2
✓ Branch 0 taken 5770 times.
✗ Branch 1 not taken.
15818 entry.fullpath = duplicate_string(printable_stack[i].fullpath);
126
1/2
✓ Branch 0 taken 5770 times.
✗ Branch 1 not taken.
15818 entry.prettypath = duplicate_string(printable_stack[i].prettypath);
127
1/2
✓ Branch 0 taken 5770 times.
✗ Branch 1 not taken.
15818 entry.lineno = printable_stack[i].lineno;
128
1/2
✓ Branch 0 taken 5770 times.
✗ Branch 1 not taken.
15818 entry.details = duplicate_string(printable_stack[i].details);
129 }
130 466 }
131
132 static bool ismath=false;
133 static string matherror;
134
135 903 void error_interface(int errid, int whichpass, const char * e_)
136 {
137 903 errored = true;
138
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 901 times.
903 if (ismath) matherror = e_;
139
2/2
✓ Branch 0 taken 382 times.
✓ Branch 1 taken 519 times.
901 else if (pass == whichpass) {
140 // don't show current block if the error came from an error command
141 382 bool show_block = (errid != error_id_error_command);
142
7/14
✓ Branch 0 taken 382 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 382 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 192 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 192 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 192 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 192 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 192 times.
✗ Branch 13 not taken.
572 fillerror(errors[numerror++], get_error_name((asar_error_id)errid), STR "error: (" + get_error_name((asar_error_id)errid) + "): ", e_, show_block);
143 }
144 else {}//ignore anything else
145 903 }
146
147 84 void warn(int errid, const char * str)
148 {
149 // don't show current block if the warning came from a warn command
150 84 bool show_block = (errid != warning_id_warn_command);
151
7/14
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 44 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 44 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 44 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 44 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 44 times.
✗ Branch 13 not taken.
124 fillerror(warnings[numwarn++], get_warning_name((asar_warning_id)errid), STR "warning: (" + get_warning_name((asar_warning_id)errid) + "): ", str, show_block);
152 84 }
153
154 static autoarray<labeldata> ldata;
155 static int labelsinldata = 0;
156 static autoarray<definedata> ddata;
157 static int definesinddata=0;
158
159 520 static void resetdllstuff()
160 {
161 #define free_and_null(x) free((void*)x); x = nullptr
162
2/2
✓ Branch 0 taken 190 times.
✓ Branch 1 taken 520 times.
710 for (int i=0;i<numprint;i++)
163 {
164 190 free_and_null(prints[i]);
165 }
166 520 prints.reset();
167 520 numprint=0;
168
169
2/2
✓ Branch 0 taken 382 times.
✓ Branch 1 taken 520 times.
902 for (int i=0;i<numerror;i++)
170 {
171 382 free_and_null(errors[i].filename);
172 382 free_and_null(errors[i].rawerrdata);
173 382 free_and_null(errors[i].fullerrdata);
174 382 free_and_null(errors[i].block);
175 382 free_and_null(errors[i].errname);
176
177
2/2
✓ Branch 0 taken 15814 times.
✓ Branch 1 taken 382 times.
16386 for (int j=0;j<errors[i].callstacksize;++j)
178 {
179 15814 stackentry& entry = const_cast<stackentry&>(errors[i].callstack[j]);
180 15814 free_and_null(entry.fullpath);
181 15814 free_and_null(entry.prettypath);
182 15814 free_and_null(entry.details);
183 }
184 382 free_and_null(errors[i].callstack);
185 }
186 520 errors.reset();
187 520 numerror=0;
188
189
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 520 times.
602 for (int i=0;i<numwarn;i++)
190 {
191 82 free_and_null(warnings[i].filename);
192 82 free_and_null(warnings[i].rawerrdata);
193 82 free_and_null(warnings[i].fullerrdata);
194 82 free_and_null(warnings[i].block);
195 82 free_and_null(warnings[i].errname);
196
197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 82 times.
122 for (int j=0;j<warnings[i].callstacksize;++j)
198 {
199 stackentry& entry = const_cast<stackentry&>(warnings[i].callstack[j]);
200 free_and_null(entry.fullpath);
201 free_and_null(entry.prettypath);
202 free_and_null(entry.details);
203 }
204 82 free_and_null(warnings[i].callstack);
205 }
206 520 warnings.reset();
207 520 numwarn=0;
208
209
2/2
✓ Branch 0 taken 2289 times.
✓ Branch 1 taken 520 times.
2809 for (int i=0;i<definesinddata;i++)
210 {
211 2289 free_and_null(ddata[i].name);
212 2289 free_and_null(ddata[i].contents);
213 }
214 520 ddata.reset();
215 520 definesinddata=0;
216
217
2/2
✓ Branch 0 taken 365 times.
✓ Branch 1 taken 520 times.
885 for (int i=0;i<labelsinldata;i++)
218 365 free((void*)ldata[i].name);
219 520 ldata.reset();
220 520 labelsinldata=0;
221 #undef free_and_null
222
223 520 romCrc = 0;
224 520 clidefines.reset();
225 520 reset_warnings_to_default();
226
227 520 reseteverything();
228 520 }
229
230 #define maxromsize (16*1024*1024)
231
232 static bool expectsNewAPI = false;
233
234 367 static void addlabel(const string & name, const snes_label & label_data)
235 {
236 labeldata label;
237 367 label.name = strdup(name);
238 367 label.location = (int)(label_data.pos & 0xFFFFFF);
239
1/2
✓ Branch 0 taken 187 times.
✗ Branch 1 not taken.
367 ldata[labelsinldata++] = label;
240 367 }
241
242 /* $EXPORTSTRUCT_PP$
243 */
244 struct patchparams_v200 : public patchparams_base
245 {
246 // Same parameters as asar_patch()
247 const char * patchloc;
248 char * romdata;
249 int buflen;
250 int * romlen;
251
252 // Include paths to use when searching files.
253 const char** includepaths;
254 int numincludepaths;
255
256 // A list of additional defines to make available to the patch.
257 const struct definedata* additional_defines;
258 int additional_define_count;
259
260 // Path to a text file to parse standard include search paths from.
261 // Set to NULL to not use any standard includes search paths.
262 const char* stdincludesfile;
263
264 // Path to a text file to parse standard defines from.
265 // Set to NULL to not use any standard defines.
266 const char* stddefinesfile;
267
268 // A list of warnings to enable or disable.
269 // Specify warnings in the format "WXXXX" where XXXX = warning ID.
270 const struct warnsetting * warning_settings;
271 int warning_setting_count;
272
273 // List of memory files to create on the virtual filesystem.
274 const struct memoryfile * memory_files;
275 int memory_file_count;
276
277 // Set override_checksum_gen to true and generate_checksum to true/false
278 // to force generating/not generating a checksum.
279 bool override_checksum_gen;
280 bool generate_checksum;
281
282 // Set this to true for generated error and warning texts to always
283 // contain their full call stack.
284 bool full_call_stack;
285 };
286
287 /* $EXPORTSTRUCT_PP$
288 */
289 struct patchparams : public patchparams_v200
290 {
291
292 };
293
294 515 static void asar_patch_begin(char * romdata_, int buflen, int * romlen_)
295 {
296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 515 times.
515 if (buflen != maxromsize)
297 {
298 romdata_r = (unsigned char*)malloc(maxromsize);
299 memcpy(const_cast<unsigned char*>(romdata_r)/*we just allocated this, it's safe to violate its const*/, romdata_, (size_t)*romlen_);
300 }
301 515 else romdata_r = (unsigned char*)romdata_;
302 515 romdata = (unsigned char*)malloc(maxromsize);
303 // RPG Hacker: Without this memset, freespace commands can (and probably will) fail.
304 515 memset((void*)romdata, 0, maxromsize);
305 515 memcpy(const_cast<unsigned char*>(romdata), romdata_, (size_t)*romlen_);
306 515 resetdllstuff();
307 515 romlen = *romlen_;
308 515 romlen_r = *romlen_;
309 515 }
310
311 515 static void asar_patch_main(const char * patchloc)
312 {
313
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 514 times.
515 if (!path_is_absolute(patchloc)) asar_throw_warning(pass, warning_id_relative_path_used, "patch file");
314
315 try
316 {
317
2/2
✓ Branch 0 taken 1505 times.
✓ Branch 1 taken 495 times.
2000 for (pass = 0;pass < 3;pass++)
318 {
319
1/2
✓ Branch 0 taken 1505 times.
✗ Branch 1 not taken.
1505 initstuff();
320
2/2
✓ Branch 0 taken 1485 times.
✓ Branch 1 taken 20 times.
1505 assemblefile(patchloc);
321 // RPG Hacker: Necessary, because finishpass() can throws warning and errors.
322
2/4
✓ Branch 0 taken 1485 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 786 times.
✗ Branch 3 not taken.
2184 callstack_push cs_push(callstack_entry_type::FILE, filesystem->create_absolute_path(nullptr, patchloc));
323
1/2
✓ Branch 0 taken 1485 times.
✗ Branch 1 not taken.
1485 finishpass();
324 1485 }
325 }
326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 catch (errfatal&) {}
327 515 }
328
329 515 static bool asar_patch_end(char * romdata_, int buflen, int * romlen_)
330 {
331
2/2
✓ Branch 0 taken 261 times.
✓ Branch 1 taken 254 times.
515 if (checksum_fix_enabled) fixchecksum();
332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 515 times.
515 if (romdata_ != (const char*)romdata_r) free(const_cast<unsigned char*>(romdata_r));
333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 515 times.
515 if (buflen < romlen) asar_throw_error(pass, error_type_null, error_id_buffer_too_small);
334
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 378 times.
515 if (errored)
335 {
336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 137 times.
137 if (numerror==0)
337 asar_throw_error(pass, error_type_null, error_id_internal_error, "phantom error");
338 137 free(const_cast<unsigned char*>(romdata));
339 137 return false;
340 }
341
1/2
✓ Branch 0 taken 378 times.
✗ Branch 1 not taken.
378 if (*romlen_ != buflen)
342 {
343 378 *romlen_ = romlen;
344 }
345 378 romCrc = crc32((const uint8_t*)romdata, (size_t)romlen);
346 378 memcpy(romdata_, romdata, (size_t)romlen);
347 378 free(const_cast<unsigned char*>(romdata));
348 378 return true;
349 }
350
351 #if defined(__clang__)
352 # pragma clang diagnostic push
353 # pragma clang diagnostic ignored "-Wmissing-prototypes"
354 #endif
355
356 // this and asar_close are hardcoded in each api
357 6 EXPORT bool asar_init()
358 {
359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
6 if (!expectsNewAPI) return false;
360 4 return true;
361 }
362
363 /* $EXPORT$
364 * Returns the version, in the format major*10000+minor*100+bugfix*1. This
365 * means that 1.2.34 would be returned as 10234.
366 */
367 180 EXPORT int asar_version()
368 {
369 180 return get_version_int();
370 }
371
372 /* $EXPORT$
373 * Returns the API version, format major*100+minor. Minor is incremented on
374 * backwards compatible changes; major is incremented on incompatible changes.
375 * Does not have any correlation with the Asar version.
376 *
377 * It's not very useful directly, since asar_init() verifies this automatically.
378 * Calling this one also sets a flag that makes asar_init not instantly return
379 * false; this is so programs expecting an older API won't do anything unexpected.
380 */
381 12 EXPORT int asar_apiversion()
382 {
383 12 expectsNewAPI=true;
384 12 return APIVERSION;
385 }
386
387 /* $EXPORT$
388 * Clears out all errors, warnings and printed statements, and clears the file
389 * cache. Not really useful, since asar_patch() already does this.
390 */
391 EXPORT bool asar_reset()
392 {
393 resetdllstuff();
394 pass=0;
395 return true;
396 }
397
398 5 EXPORT void asar_close()
399 {
400 5 resetdllstuff();
401 5 }
402
403 /* $EXPORT$
404 * Applies a patch. The first argument is a filename (so Asar knows where to
405 * look for incsrc'd stuff); however, the ROM is in memory.
406 * This function assumes there are no headers anywhere, neither in romdata nor
407 * the sizes. romlen may be altered by this function; if this is undesirable,
408 * set romlen equal to buflen.
409 * The return value is whether any errors appeared (false=errors, call
410 * asar_geterrors for details). If there is an error, romdata and romlen will
411 * be left unchanged.
412 * See the documentation of struct patchparams for more information.
413 */
414 515 EXPORT bool asar_patch(const struct patchparams_base *params)
415 {
416 515 auto execute_patch = [&]() {
417
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 515 times.
515 if (params == nullptr)
418 {
419 asar_throw_error(pass, error_type_null, error_id_params_null);
420 }
421
422
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 515 times.
515 if (params->structsize != sizeof(patchparams_v200))
423 {
424 asar_throw_error(pass, error_type_null, error_id_params_invalid_size);
425 }
426
427 patchparams paramscurrent;
428 515 memset(&paramscurrent, 0, sizeof(paramscurrent));
429 515 memcpy(&paramscurrent, params, (size_t)params->structsize);
430
431
432
1/2
✓ Branch 0 taken 272 times.
✗ Branch 1 not taken.
515 asar_patch_begin(paramscurrent.romdata, paramscurrent.buflen, paramscurrent.romlen);
433
434 515 simple_callstacks = !paramscurrent.full_call_stack;
435
436 272 autoarray<string> includepaths;
437 272 autoarray<const char*> includepath_cstrs;
438
439
2/2
✓ Branch 0 taken 246 times.
✓ Branch 1 taken 515 times.
761 for (int i = 0; i < paramscurrent.numincludepaths; ++i)
440 {
441
2/6
✓ Branch 0 taken 246 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 246 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
246 if (!path_is_absolute(paramscurrent.includepaths[i])) asar_throw_warning(pass, warning_id_relative_path_used, "include search");
442
2/4
✓ Branch 0 taken 123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 123 times.
✗ Branch 3 not taken.
246 string& newpath = includepaths.append(paramscurrent.includepaths[i]);
443
1/2
✓ Branch 0 taken 123 times.
✗ Branch 1 not taken.
246 includepath_cstrs.append((const char*)newpath);
444 }
445
446
2/2
✓ Branch 0 taken 247 times.
✓ Branch 1 taken 268 times.
515 if (paramscurrent.stdincludesfile != nullptr) {
447
2/6
✓ Branch 0 taken 247 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 247 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
247 if (!path_is_absolute(paramscurrent.stdincludesfile)) asar_throw_warning(pass, warning_id_relative_path_used, "std includes file");
448
1/2
✓ Branch 0 taken 124 times.
✗ Branch 1 not taken.
124 string stdincludespath = paramscurrent.stdincludesfile;
449
1/2
✓ Branch 0 taken 247 times.
✗ Branch 1 not taken.
247 parse_std_includes(stdincludespath, includepaths);
450 247 }
451
452
2/2
✓ Branch 0 taken 495 times.
✓ Branch 1 taken 515 times.
1010 for (int i = 0; i < includepaths.count; ++i)
453 {
454
2/4
✓ Branch 0 taken 249 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 249 times.
✗ Branch 3 not taken.
495 includepath_cstrs.append((const char*)includepaths[i]);
455 }
456
457 515 size_t includepath_count = (size_t)includepath_cstrs.count;
458
1/2
✓ Branch 0 taken 272 times.
✗ Branch 1 not taken.
272 virtual_filesystem new_filesystem;
459
2/4
✓ Branch 0 taken 515 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 272 times.
✗ Branch 3 not taken.
515 new_filesystem.initialize(&includepath_cstrs[0], includepath_count);
460 515 filesystem = &new_filesystem;
461
462
2/2
✓ Branch 0 taken 279 times.
✓ Branch 1 taken 515 times.
794 for(int i = 0; i < paramscurrent.memory_file_count; ++i) {
463 279 memoryfile f = paramscurrent.memory_files[i];
464
1/2
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
279 filesystem->add_memory_file(f.path, f.buffer, f.length);
465 }
466
467 515 clidefines.reset();
468
2/2
✓ Branch 0 taken 987 times.
✓ Branch 1 taken 515 times.
1502 for (int i = 0; i < paramscurrent.additional_define_count; ++i)
469 {
470
2/4
✓ Branch 0 taken 987 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 495 times.
✗ Branch 3 not taken.
987 string name = (paramscurrent.additional_defines[i].name != nullptr ? paramscurrent.additional_defines[i].name : "");
471
1/2
✓ Branch 0 taken 495 times.
✗ Branch 1 not taken.
987 strip_whitespace(name);
472
1/2
✓ Branch 0 taken 495 times.
✗ Branch 1 not taken.
987 name.strip_prefix('!'); // remove leading ! if present
473
2/6
✓ Branch 0 taken 987 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 987 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
987 if (!validatedefinename(name)) asar_throw_error(pass, error_type_null, error_id_cmdl_define_invalid, "asar_patch_ex() additional defines", name.data());
474
3/4
✓ Branch 0 taken 495 times.
✓ Branch 1 taken 492 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 495 times.
987 if (clidefines.exists(name)) {
475 asar_throw_error(pass, error_type_null, error_id_cmdl_define_override, "asar_patch_ex() additional define", name.data());
476 return false;
477 }
478
3/4
✓ Branch 0 taken 741 times.
✓ Branch 1 taken 246 times.
✓ Branch 2 taken 495 times.
✗ Branch 3 not taken.
987 string contents = (paramscurrent.additional_defines[i].contents != nullptr ? paramscurrent.additional_defines[i].contents : "");
479
2/4
✓ Branch 0 taken 987 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 495 times.
✗ Branch 3 not taken.
987 clidefines.create(name) = contents;
480
1/2
✓ Branch 0 taken 495 times.
✗ Branch 1 not taken.
987 }
481
482
2/2
✓ Branch 0 taken 247 times.
✓ Branch 1 taken 268 times.
515 if (paramscurrent.stddefinesfile != nullptr) {
483
2/6
✓ Branch 0 taken 247 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 247 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
247 if (!path_is_absolute(paramscurrent.stddefinesfile)) asar_throw_warning(pass, warning_id_relative_path_used, "std defines file");
484
1/2
✓ Branch 0 taken 124 times.
✗ Branch 1 not taken.
124 string stddefinespath = paramscurrent.stddefinesfile;
485
1/2
✓ Branch 0 taken 247 times.
✗ Branch 1 not taken.
247 parse_std_defines(stddefinespath);
486 247 } else {
487
1/2
✓ Branch 0 taken 268 times.
✗ Branch 1 not taken.
268 parse_std_defines(nullptr); // needed to populate builtin defines
488 }
489
490
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 515 times.
517 for (int i = 0; i < paramscurrent.warning_setting_count; ++i)
491 {
492
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 asar_warning_id warnid = parse_warning_id_from_string(paramscurrent.warning_settings[i].warnid);
493
494
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (warnid != warning_id_end)
495 {
496
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 set_warning_enabled(warnid, paramscurrent.warning_settings[i].enabled);
497 }
498 else
499 {
500 asar_throw_warning(pass, warning_id_invalid_warning_id, paramscurrent.warning_settings[i].warnid, "asar_patch_ex() warning_settings");
501 }
502 }
503
504
2/2
✓ Branch 0 taken 244 times.
✓ Branch 1 taken 271 times.
515 if(paramscurrent.override_checksum_gen) {
505 244 checksum_fix_enabled = paramscurrent.generate_checksum;
506 244 force_checksum_fix = true;
507 }
508
509
1/2
✓ Branch 0 taken 515 times.
✗ Branch 1 not taken.
515 asar_patch_main(paramscurrent.patchloc);
510
511 // RPG Hacker: Required before the destroy() below,
512 // otherwise it will leak memory.
513
1/2
✓ Branch 0 taken 515 times.
✗ Branch 1 not taken.
515 closecachedfiles();
514
515
1/2
✓ Branch 0 taken 515 times.
✗ Branch 1 not taken.
515 new_filesystem.destroy();
516 515 filesystem = nullptr;
517
518
1/2
✓ Branch 0 taken 515 times.
✗ Branch 1 not taken.
515 return asar_patch_end(paramscurrent.romdata, paramscurrent.buflen, paramscurrent.romlen);
519 515 };
520 #if defined(RUN_VIA_FIBER)
521 243 return run_as_fiber(execute_patch);
522 #elif defined(RUN_VIA_THREAD)
523
1/2
✓ Branch 0 taken 272 times.
✗ Branch 1 not taken.
544 return run_as_thread(execute_patch);
524 #else
525 return execute_patch();
526 #endif
527 }
528
529 /* $EXPORT$
530 * Returns the maximum possible size of the output ROM from asar_patch().
531 * Giving this size to buflen guarantees you will not get any buffer too small
532 * errors; however, it is safe to give smaller buffers if you don't expect any
533 * ROMs larger than 4MB or something.
534 */
535 235 EXPORT int asar_maxromsize()
536 {
537 235 return maxromsize;
538 }
539
540 /* $EXPORT$
541 * Get a list of all errors.
542 * All pointers from these functions are valid only until the same function is
543 * called again, or until asar_patch, asar_reset or asar_close is called,
544 * whichever comes first. Copy the contents if you need it for a longer time.
545 */
546 505 EXPORT const struct errordata * asar_geterrors(int * count)
547 {
548 505 *count=numerror;
549 505 return errors;
550 }
551
552 /* $EXPORT$
553 * Get a list of all warnings.
554 */
555 505 EXPORT const struct errordata * asar_getwarnings(int * count)
556 {
557 505 *count=numwarn;
558 505 return warnings;
559 }
560
561 /* $EXPORT$
562 * Get a list of all printed data.
563 */
564 487 EXPORT const char * const * asar_getprints(int * count)
565 {
566 487 *count=numprint;
567 487 return prints;
568 }
569
570 /* $EXPORT$
571 * Get a list of all labels.
572 */
573 180 EXPORT const struct labeldata * asar_getalllabels(int * count)
574 {
575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 180 times.
180 for (int i=0;i<labelsinldata;i++) free((void*)ldata[i].name);
576 180 labelsinldata=0;
577 180 labels.each(addlabel);
578 180 *count=labelsinldata;
579 180 return ldata;
580 }
581
582 /* $EXPORT$
583 * Get the ROM location of one label. -1 means "not found".
584 */
585 6 EXPORT int asar_getlabelval(const char * name)
586 {
587 int i;
588 try {
589
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 i=(int)labelval(&name).pos;
590 }
591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 catch(errfatal&) { return -1; }
592
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (*name || i<0) return -1;
593 4 else return i&0xFFFFFF;
594 }
595
596 /* $EXPORT$
597 * Get the value of a define.
598 */
599 182 EXPORT const char * asar_getdefine(const char * name)
600 {
601
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 91 times.
182 if (!defines.exists(name)) return "";
602 4 return defines.find(name);
603 }
604
605 /* $EXPORT$
606 * Parses all defines in the parameter.
607 * If there were any errors, returns an empty string.
608 */
609 6 EXPORT const char * asar_resolvedefines(const char * data)
610 {
611
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
7 static string out;
612 5 out = "";
613 try
614 {
615
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 resolvedefines(out, data);
616 }
617
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 catch(errfatal&){
618
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 out = "";
619 1 }
620 6 return out;
621 }
622
623 2295 static void adddef(const string& name, string& value)
624 {
625 definedata define;
626 2295 define.name= duplicate_string(name);
627 2295 define.contents= duplicate_string(value);
628
1/2
✓ Branch 0 taken 1159 times.
✗ Branch 1 not taken.
2295 ddata[definesinddata++]=define;
629 2295 }
630
631 /* $EXPORT$
632 * Gets the values and names of all defines.
633 */
634 182 EXPORT const struct definedata * asar_getalldefines(int * count)
635 {
636
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 182 times.
182 for (int i=0;i<definesinddata;i++)
637 {
638 free((void*)ddata[i].name);
639 free((void*)ddata[i].contents);
640 }
641 182 definesinddata=0;
642 182 defines.each(adddef);
643 182 *count=definesinddata;
644 182 return ddata;
645 }
646
647 /* $EXPORT$
648 * Parses a string containing math. It automatically assumes global scope (no
649 * namespaces), and has access to all functions and labels from the last call
650 * to asar_patch. Remember to check error to see if it's successful (NULL) or
651 * if it failed (non-NULL, contains a descriptive string). It does not affect
652 * asar_geterrors.
653 */
654 183 EXPORT double asar_math(const char * math_, const char ** error)
655 {
656 94 ns="";
657 183 namespace_list.reset();
658 183 sublabels.reset();
659 183 errored=false;
660 183 ismath=true;
661 183 initmathcore();
662 94 double rval=0;
663 try
664 {
665
2/2
✓ Branch 0 taken 181 times.
✓ Branch 1 taken 2 times.
183 rval=(double)math(math_);
666 }
667
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 catch(errfatal&)
668 {
669 2 *error=matherror;
670 2 }
671 183 ismath=false;
672 183 deinitmathcore();
673 183 return rval;
674 }
675
676 /* $EXPORT$
677 * Get a list of all the blocks written to the ROM by calls such as
678 * asar_patch().
679 */
680 182 EXPORT const struct writtenblockdata * asar_getwrittenblocks(int * count)
681 {
682 182 *count = writtenblocks.count;
683 182 return writtenblocks;
684 }
685
686 /* $EXPORT$
687 * Get the mapper currently used by Asar.
688 */
689 187 EXPORT enum mapper_t asar_getmapper()
690 {
691 187 return mapper;
692 }
693
694 /* $EXPORT$
695 * Generates the contents of a symbols file for in a specific format.
696 */
697 180 EXPORT const char * asar_getsymbolsfile(const char* type){
698
3/6
✓ Branch 0 taken 180 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 91 times.
✗ Branch 5 not taken.
180 symbolsfile = create_symbols_file(type, romCrc);
699 180 return symbolsfile;
700 }
701
702 #if defined(__clang__)
703 # pragma clang diagnostic pop
704 #endif
705