asar coverage - build #154


src/asar/
File: src/asar/interface-lib.cpp
Date: 2024-01-25 23:09:18
Lines:
251/273
91.9%
Functions:
29/30
96.7%
Branches:
152/270
56.3%

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 468 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.
468 const char* current_filename = get_current_file_name();
102
2/2
✓ Branch 0 taken 467 times.
✓ Branch 1 taken 1 times.
468 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.
468 myerr.line=get_current_line();
105
1/2
✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
468 const char* current_block = get_current_block();
106
2/2
✓ Branch 0 taken 447 times.
✓ Branch 1 taken 21 times.
468 if (current_block) myerr.block= duplicate_string(current_block);
107 21 else myerr.block= duplicate_string("");
108 468 myerr.rawerrdata= duplicate_string(str);
109 236 string location;
110 236 string details;
111
1/2
✓ Branch 0 taken 468 times.
✗ Branch 1 not taken.
468 get_current_line_details(&location, &details);
112
6/12
✓ Branch 0 taken 468 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.
700 myerr.fullerrdata= duplicate_string(location+": "+type+str+details+get_callstack());
113 468 myerr.errname = duplicate_string(errname);
114
115 236 autoarray<printable_callstack_entry> printable_stack;
116
1/2
✓ Branch 0 taken 468 times.
✗ Branch 1 not taken.
468 get_full_printable_callstack(&printable_stack, 0, false);
117
118 468 myerr.callstacksize = printable_stack.count;
119 468 myerr.callstack = static_cast<stackentry*>(malloc(sizeof(stackentry) * myerr.callstacksize));
120
121
2/2
✓ Branch 0 taken 15798 times.
✓ Branch 1 taken 468 times.
16266 for (int i = 0; i < myerr.callstacksize; ++i)
122 {
123 15798 stackentry& entry = const_cast<stackentry&>(myerr.callstack[i]);
124
125
1/2
✓ Branch 0 taken 5750 times.
✗ Branch 1 not taken.
15798 entry.fullpath = duplicate_string(printable_stack[i].fullpath);
126
1/2
✓ Branch 0 taken 5750 times.
✗ Branch 1 not taken.
15798 entry.prettypath = duplicate_string(printable_stack[i].prettypath);
127
1/2
✓ Branch 0 taken 5750 times.
✗ Branch 1 not taken.
15798 entry.lineno = printable_stack[i].lineno;
128
1/2
✓ Branch 0 taken 5750 times.
✗ Branch 1 not taken.
15798 entry.details = duplicate_string(printable_stack[i].details);
129 }
130 468 }
131
132 static bool ismath=false;
133 static string matherror;
134
135 975 void error_interface(int errid, int whichpass, const char * e_)
136 {
137 975 errored = true;
138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 975 times.
975 if (ismath) matherror = e_;
139
2/2
✓ Branch 0 taken 402 times.
✓ Branch 1 taken 573 times.
975 else if (pass == whichpass) {
140 // don't show current block if the error came from an error command
141 402 bool show_block = (errid != error_id_error_command);
142
7/14
✓ Branch 0 taken 402 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 402 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 202 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 202 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 202 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 202 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 202 times.
✗ Branch 13 not taken.
602 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 975 }
146
147 66 void warn(int errid, const char * str)
148 {
149 // don't show current block if the warning came from a warn command
150 66 bool show_block = (errid != warning_id_warn_command);
151
7/14
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 34 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 34 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 34 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 34 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 34 times.
✗ Branch 13 not taken.
98 fillerror(warnings[numwarn++], get_warning_name((asar_warning_id)errid), STR "warning: (" + get_warning_name((asar_warning_id)errid) + "): ", str, show_block);
152 66 }
153
154 static autoarray<labeldata> ldata;
155 static int labelsinldata = 0;
156 static autoarray<definedata> ddata;
157 static int definesinddata=0;
158
159 496 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 496 times.
686 for (int i=0;i<numprint;i++)
163 {
164 190 free_and_null(prints[i]);
165 }
166 496 prints.reset();
167 496 numprint=0;
168
169
2/2
✓ Branch 0 taken 402 times.
✓ Branch 1 taken 496 times.
898 for (int i=0;i<numerror;i++)
170 {
171 402 free_and_null(errors[i].filename);
172 402 free_and_null(errors[i].rawerrdata);
173 402 free_and_null(errors[i].fullerrdata);
174 402 free_and_null(errors[i].block);
175 402 free_and_null(errors[i].errname);
176
177
2/2
✓ Branch 0 taken 15798 times.
✓ Branch 1 taken 402 times.
16400 for (int j=0;j<errors[i].callstacksize;++j)
178 {
179 15798 stackentry& entry = const_cast<stackentry&>(errors[i].callstack[j]);
180 15798 free_and_null(entry.fullpath);
181 15798 free_and_null(entry.prettypath);
182 15798 free_and_null(entry.details);
183 }
184 402 free_and_null(errors[i].callstack);
185 }
186 496 errors.reset();
187 496 numerror=0;
188
189
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 496 times.
562 for (int i=0;i<numwarn;i++)
190 {
191 66 free_and_null(warnings[i].filename);
192 66 free_and_null(warnings[i].rawerrdata);
193 66 free_and_null(warnings[i].fullerrdata);
194 66 free_and_null(warnings[i].block);
195 66 free_and_null(warnings[i].errname);
196
197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
98 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 66 free_and_null(warnings[i].callstack);
205 }
206 496 warnings.reset();
207 496 numwarn=0;
208
209
2/2
✓ Branch 0 taken 2145 times.
✓ Branch 1 taken 496 times.
2641 for (int i=0;i<definesinddata;i++)
210 {
211 2145 free_and_null(ddata[i].name);
212 2145 free_and_null(ddata[i].contents);
213 }
214 496 ddata.reset();
215 496 definesinddata=0;
216
217
2/2
✓ Branch 0 taken 343 times.
✓ Branch 1 taken 496 times.
839 for (int i=0;i<labelsinldata;i++)
218 343 free((void*)ldata[i].name);
219 496 ldata.reset();
220 496 labelsinldata=0;
221 #undef free_and_null
222
223 496 romCrc = 0;
224 496 clidefines.reset();
225 496 reset_warnings_to_default();
226
227 496 reseteverything();
228 496 }
229
230 #define maxromsize (16*1024*1024)
231
232 static bool expectsNewAPI = false;
233
234 343 static void addlabel(const string & name, const snes_label & label_data)
235 {
236 labeldata label;
237 343 label.name = strdup(name);
238 343 label.location = (int)(label_data.pos & 0xFFFFFF);
239
1/2
✓ Branch 0 taken 174 times.
✗ Branch 1 not taken.
343 ldata[labelsinldata++] = label;
240 343 }
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 491 static void asar_patch_begin(char * romdata_, int buflen, int * romlen_)
295 {
296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 491 times.
491 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 491 else romdata_r = (unsigned char*)romdata_;
302 491 romdata = (unsigned char*)malloc(maxromsize);
303 // RPG Hacker: Without this memset, freespace commands can (and probably will) fail.
304 491 memset((void*)romdata, 0, maxromsize);
305 491 memcpy(const_cast<unsigned char*>(romdata), romdata_, (size_t)*romlen_);
306 491 resetdllstuff();
307 491 romlen = *romlen_;
308 491 romlen_r = *romlen_;
309 491 }
310
311 491 static void asar_patch_main(const char * patchloc)
312 {
313
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 490 times.
491 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 1433 times.
✓ Branch 1 taken 471 times.
1904 for (pass = 0;pass < 3;pass++)
318 {
319
1/2
✓ Branch 0 taken 1433 times.
✗ Branch 1 not taken.
1433 initstuff();
320
2/2
✓ Branch 0 taken 1413 times.
✓ Branch 1 taken 20 times.
1433 assemblefile(patchloc);
321 // RPG Hacker: Necessary, because finishpass() can throws warning and errors.
322
2/4
✓ Branch 0 taken 1413 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 738 times.
✗ Branch 3 not taken.
2088 callstack_push cs_push(callstack_entry_type::FILE, filesystem->create_absolute_path(nullptr, patchloc));
323
1/2
✓ Branch 0 taken 1413 times.
✗ Branch 1 not taken.
1413 finishpass();
324 1413 }
325 }
326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 catch (errfatal&) {}
327 491 }
328
329 491 static bool asar_patch_end(char * romdata_, int buflen, int * romlen_)
330 {
331
2/2
✓ Branch 0 taken 246 times.
✓ Branch 1 taken 245 times.
491 if (checksum_fix_enabled) fixchecksum();
332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 491 times.
491 if (romdata_ != (const char*)romdata_r) free(const_cast<unsigned char*>(romdata_r));
333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 491 times.
491 if (buflen < romlen) asar_throw_error(pass, error_type_null, error_id_buffer_too_small);
334
2/2
✓ Branch 0 taken 145 times.
✓ Branch 1 taken 346 times.
491 if (errored)
335 {
336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 145 times.
145 if (numerror==0)
337 asar_throw_error(pass, error_type_null, error_id_phantom_error);
338 145 free(const_cast<unsigned char*>(romdata));
339 145 return false;
340 }
341
1/2
✓ Branch 0 taken 346 times.
✗ Branch 1 not taken.
346 if (*romlen_ != buflen)
342 {
343 346 *romlen_ = romlen;
344 }
345 346 romCrc = crc32((const uint8_t*)romdata, (size_t)romlen);
346 346 memcpy(romdata_, romdata, (size_t)romlen);
347 346 free(const_cast<unsigned char*>(romdata));
348 346 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 5 EXPORT bool asar_init()
358 {
359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
5 if (!expectsNewAPI) return false;
360 3 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 167 EXPORT int asar_version()
368 {
369 167 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 9 EXPORT int asar_apiversion()
382 {
383 9 expectsNewAPI=true;
384 9 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 491 EXPORT bool asar_patch(const struct patchparams_base *params)
415 {
416 491 auto execute_patch = [&]() {
417
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 491 times.
491 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 491 times.
491 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 491 memset(&paramscurrent, 0, sizeof(paramscurrent));
429 491 memcpy(&paramscurrent, params, (size_t)params->structsize);
430
431
432
1/2
✓ Branch 0 taken 256 times.
✗ Branch 1 not taken.
491 asar_patch_begin(paramscurrent.romdata, paramscurrent.buflen, paramscurrent.romlen);
433
434 491 simple_callstacks = !paramscurrent.full_call_stack;
435
436 256 autoarray<string> includepaths;
437 256 autoarray<const char*> includepath_cstrs;
438
439
2/2
✓ Branch 0 taken 238 times.
✓ Branch 1 taken 491 times.
729 for (int i = 0; i < paramscurrent.numincludepaths; ++i)
440 {
441
2/6
✓ Branch 0 taken 238 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 238 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
238 if (!path_is_absolute(paramscurrent.includepaths[i])) asar_throw_warning(pass, warning_id_relative_path_used, "include search");
442
2/4
✓ Branch 0 taken 119 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 119 times.
✗ Branch 3 not taken.
238 string& newpath = includepaths.append(paramscurrent.includepaths[i]);
443
1/2
✓ Branch 0 taken 119 times.
✗ Branch 1 not taken.
238 includepath_cstrs.append((const char*)newpath);
444 }
445
446
2/2
✓ Branch 0 taken 239 times.
✓ Branch 1 taken 252 times.
491 if (paramscurrent.stdincludesfile != nullptr) {
447
2/6
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 239 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
239 if (!path_is_absolute(paramscurrent.stdincludesfile)) asar_throw_warning(pass, warning_id_relative_path_used, "std includes file");
448
1/2
✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
120 string stdincludespath = paramscurrent.stdincludesfile;
449
1/2
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
239 parse_std_includes(stdincludespath, includepaths);
450 239 }
451
452
2/2
✓ Branch 0 taken 479 times.
✓ Branch 1 taken 491 times.
970 for (int i = 0; i < includepaths.count; ++i)
453 {
454
2/4
✓ Branch 0 taken 241 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 241 times.
✗ Branch 3 not taken.
479 includepath_cstrs.append((const char*)includepaths[i]);
455 }
456
457 491 size_t includepath_count = (size_t)includepath_cstrs.count;
458
1/2
✓ Branch 0 taken 256 times.
✗ Branch 1 not taken.
256 virtual_filesystem new_filesystem;
459
2/4
✓ Branch 0 taken 491 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 256 times.
✗ Branch 3 not taken.
491 new_filesystem.initialize(&includepath_cstrs[0], includepath_count);
460 491 filesystem = &new_filesystem;
461
462
2/2
✓ Branch 0 taken 263 times.
✓ Branch 1 taken 491 times.
754 for(int i = 0; i < paramscurrent.memory_file_count; ++i) {
463 263 memoryfile f = paramscurrent.memory_files[i];
464
1/2
✓ Branch 0 taken 263 times.
✗ Branch 1 not taken.
263 filesystem->add_memory_file(f.path, f.buffer, f.length);
465 }
466
467 491 clidefines.reset();
468
2/2
✓ Branch 0 taken 954 times.
✓ Branch 1 taken 491 times.
1445 for (int i = 0; i < paramscurrent.additional_define_count; ++i)
469 {
470
2/4
✓ Branch 0 taken 954 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 478 times.
✗ Branch 3 not taken.
954 string name = (paramscurrent.additional_defines[i].name != nullptr ? paramscurrent.additional_defines[i].name : "");
471
1/2
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
954 strip_whitespace(name);
472
1/2
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
954 name.strip_prefix('!'); // remove leading ! if present
473
2/6
✓ Branch 0 taken 954 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 954 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
954 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 478 times.
✓ Branch 1 taken 476 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 478 times.
954 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 716 times.
✓ Branch 1 taken 238 times.
✓ Branch 2 taken 478 times.
✗ Branch 3 not taken.
954 string contents = (paramscurrent.additional_defines[i].contents != nullptr ? paramscurrent.additional_defines[i].contents : "");
479
2/4
✓ Branch 0 taken 954 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 478 times.
✗ Branch 3 not taken.
954 clidefines.create(name) = contents;
480
1/2
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
954 }
481
482
2/2
✓ Branch 0 taken 239 times.
✓ Branch 1 taken 252 times.
491 if (paramscurrent.stddefinesfile != nullptr) {
483
2/6
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 239 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
239 if (!path_is_absolute(paramscurrent.stddefinesfile)) asar_throw_warning(pass, warning_id_relative_path_used, "std defines file");
484
1/2
✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
120 string stddefinespath = paramscurrent.stddefinesfile;
485
1/2
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
239 parse_std_defines(stddefinespath);
486 239 } else {
487
1/2
✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
252 parse_std_defines(nullptr); // needed to populate builtin defines
488 }
489
490
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 491 times.
493 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_error(pass, error_type_null, error_id_invalid_warning_id, paramscurrent.warning_settings[i].warnid, "asar_patch_ex() warning_settings");
501 }
502 }
503
504
2/2
✓ Branch 0 taken 233 times.
✓ Branch 1 taken 258 times.
491 if(paramscurrent.override_checksum_gen) {
505 233 checksum_fix_enabled = paramscurrent.generate_checksum;
506 233 force_checksum_fix = true;
507 }
508
509
1/2
✓ Branch 0 taken 491 times.
✗ Branch 1 not taken.
491 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 491 times.
✗ Branch 1 not taken.
491 closecachedfiles();
514
515
1/2
✓ Branch 0 taken 491 times.
✗ Branch 1 not taken.
491 new_filesystem.destroy();
516 491 filesystem = nullptr;
517
518
1/2
✓ Branch 0 taken 491 times.
✗ Branch 1 not taken.
491 return asar_patch_end(paramscurrent.romdata, paramscurrent.buflen, paramscurrent.romlen);
519 491 };
520 #if defined(RUN_VIA_FIBER)
521 235 return run_as_fiber(execute_patch);
522 #elif defined(RUN_VIA_THREAD)
523
1/2
✓ Branch 0 taken 256 times.
✗ Branch 1 not taken.
512 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 208 EXPORT int asar_maxromsize()
536 {
537 208 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 487 EXPORT const struct errordata * asar_geterrors(int * count)
547 {
548 487 *count=numerror;
549 487 return errors;
550 }
551
552 /* $EXPORT$
553 * Get a list of all warnings.
554 */
555 487 EXPORT const struct errordata * asar_getwarnings(int * count)
556 {
557 487 *count=numwarn;
558 487 return warnings;
559 }
560
561 /* $EXPORT$
562 * Get a list of all printed data.
563 */
564 471 EXPORT const char * const * asar_getprints(int * count)
565 {
566 471 *count=numprint;
567 471 return prints;
568 }
569
570 /* $EXPORT$
571 * Get a list of all labels.
572 */
573 167 EXPORT const struct labeldata * asar_getalllabels(int * count)
574 {
575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 167 times.
167 for (int i=0;i<labelsinldata;i++) free((void*)ldata[i].name);
576 167 labelsinldata=0;
577 167 labels.each(addlabel);
578 167 *count=labelsinldata;
579 167 return ldata;
580 }
581
582 /* $EXPORT$
583 * Get the ROM location of one label. -1 means "not found".
584 */
585 4 EXPORT int asar_getlabelval(const char * name)
586 {
587 int i;
588 try {
589
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 i=(int)labelval(&name).pos;
590 }
591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 catch(errfatal&) { return -1; }
592
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if (*name || i<0) return -1;
593 3 else return i&0xFFFFFF;
594 }
595
596 /* $EXPORT$
597 * Get the value of a define.
598 */
599 168 EXPORT const char * asar_getdefine(const char * name)
600 {
601
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 84 times.
168 if (!defines.exists(name)) return "";
602 3 return defines.find(name);
603 }
604
605 /* $EXPORT$
606 * Parses all defines in the parameter. Note that it may emit errors.
607 */
608 2 EXPORT const char * asar_resolvedefines(const char * data)
609 {
610
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
3 static string out;
611 try
612 {
613
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 resolvedefines(out, data);
614 }
615 catch(errfatal&){}
616 2 return out;
617 }
618
619 2145 static void adddef(const string& name, string& value)
620 {
621 definedata define;
622 2145 define.name= duplicate_string(name);
623 2145 define.contents= duplicate_string(value);
624
1/2
✓ Branch 0 taken 1081 times.
✗ Branch 1 not taken.
2145 ddata[definesinddata++]=define;
625 2145 }
626
627 /* $EXPORT$
628 * Gets the values and names of all defines.
629 */
630 169 EXPORT const struct definedata * asar_getalldefines(int * count)
631 {
632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 169 times.
169 for (int i=0;i<definesinddata;i++)
633 {
634 free((void*)ddata[i].name);
635 free((void*)ddata[i].contents);
636 }
637 169 definesinddata=0;
638 169 defines.each(adddef);
639 169 *count=definesinddata;
640 169 return ddata;
641 }
642
643 /* $EXPORT$
644 * Parses a string containing math. It automatically assumes global scope (no
645 * namespaces), and has access to all functions and labels from the last call
646 * to asar_patch. Remember to check error to see if it's successful (NULL) or
647 * if it failed (non-NULL, contains a descriptive string). It does not affect
648 * asar_geterrors.
649 */
650 166 EXPORT double asar_math(const char * math_, const char ** error)
651 {
652 83 ns="";
653 166 namespace_list.reset();
654 166 sublabels.reset();
655 166 errored=false;
656 166 ismath=true;
657 166 initmathcore();
658 83 double rval=0;
659 try
660 {
661
1/2
✓ Branch 0 taken 166 times.
✗ Branch 1 not taken.
166 rval=(double)math(math_);
662 }
663 catch(errfatal&)
664 {
665 *error=matherror;
666 }
667 166 ismath=false;
668 166 deinitmathcore();
669 166 return rval;
670 }
671
672 /* $EXPORT$
673 * Get a list of all the blocks written to the ROM by calls such as
674 * asar_patch().
675 */
676 168 EXPORT const struct writtenblockdata * asar_getwrittenblocks(int * count)
677 {
678 168 *count = writtenblocks.count;
679 168 return writtenblocks;
680 }
681
682 /* $EXPORT$
683 * Get the mapper currently used by Asar.
684 */
685 174 EXPORT enum mapper_t asar_getmapper()
686 {
687 174 return mapper;
688 }
689
690 /* $EXPORT$
691 * Generates the contents of a symbols file for in a specific format.
692 */
693 166 EXPORT const char * asar_getsymbolsfile(const char* type){
694
3/6
✓ Branch 0 taken 166 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 83 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 83 times.
✗ Branch 5 not taken.
166 symbolsfile = create_symbols_file(type, romCrc);
695 166 return symbolsfile;
696 }
697
698 #if defined(__clang__)
699 # pragma clang diagnostic pop
700 #endif
701