asar coverage - build #183


src/asar/
File: src/asar/interface-lib.cpp
Date: 2024-01-29 00:15:50
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 464 static void fillerror(errordata& myerr, const char* errname, const char * type, const char * str, bool show_block)
100 {
101
1/2
✓ Branch 0 taken 234 times.
✗ Branch 1 not taken.
464 const char* current_filename = get_current_file_name();
102
2/2
✓ Branch 0 taken 463 times.
✓ Branch 1 taken 1 times.
464 if(current_filename) myerr.filename= duplicate_string(current_filename);
103 1 else myerr.filename = duplicate_string("");
104
1/2
✓ Branch 0 taken 234 times.
✗ Branch 1 not taken.
464 myerr.line=get_current_line();
105
1/2
✓ Branch 0 taken 234 times.
✗ Branch 1 not taken.
464 const char* current_block = get_current_block();
106
2/2
✓ Branch 0 taken 443 times.
✓ Branch 1 taken 21 times.
464 if (current_block) myerr.block= duplicate_string(current_block);
107 21 else myerr.block= duplicate_string("");
108 464 myerr.rawerrdata= duplicate_string(str);
109 234 string location;
110 234 string details;
111
1/2
✓ Branch 0 taken 464 times.
✗ Branch 1 not taken.
464 get_current_line_details(&location, &details);
112
6/12
✓ Branch 0 taken 464 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 234 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 234 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 234 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 234 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 234 times.
✗ Branch 11 not taken.
694 myerr.fullerrdata= duplicate_string(location+": "+type+str+details+get_callstack());
113 464 myerr.errname = duplicate_string(errname);
114
115 234 autoarray<printable_callstack_entry> printable_stack;
116
1/2
✓ Branch 0 taken 464 times.
✗ Branch 1 not taken.
464 get_full_printable_callstack(&printable_stack, 0, false);
117
118 464 myerr.callstacksize = printable_stack.count;
119 464 myerr.callstack = static_cast<stackentry*>(malloc(sizeof(stackentry) * myerr.callstacksize));
120
121
2/2
✓ Branch 0 taken 15814 times.
✓ Branch 1 taken 464 times.
16278 for (int i = 0; i < myerr.callstacksize; ++i)
122 {
123 15814 stackentry& entry = const_cast<stackentry&>(myerr.callstack[i]);
124
125
1/2
✓ Branch 0 taken 5766 times.
✗ Branch 1 not taken.
15814 entry.fullpath = duplicate_string(printable_stack[i].fullpath);
126
1/2
✓ Branch 0 taken 5766 times.
✗ Branch 1 not taken.
15814 entry.prettypath = duplicate_string(printable_stack[i].prettypath);
127
1/2
✓ Branch 0 taken 5766 times.
✗ Branch 1 not taken.
15814 entry.lineno = printable_stack[i].lineno;
128
1/2
✓ Branch 0 taken 5766 times.
✗ Branch 1 not taken.
15814 entry.details = duplicate_string(printable_stack[i].details);
129 }
130 464 }
131
132 static bool ismath=false;
133 static string matherror;
134
135 899 void error_interface(int errid, int whichpass, const char * e_)
136 {
137 899 errored = true;
138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 899 times.
899 if (ismath) matherror = e_;
139
2/2
✓ Branch 0 taken 382 times.
✓ Branch 1 taken 517 times.
899 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 899 }
146
147 82 void warn(int errid, const char * str)
148 {
149 // don't show current block if the warning came from a warn command
150 82 bool show_block = (errid != warning_id_warn_command);
151
7/14
✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 82 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 42 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 42 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 42 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 42 times.
✗ Branch 13 not taken.
122 fillerror(warnings[numwarn++], get_warning_name((asar_warning_id)errid), STR "warning: (" + get_warning_name((asar_warning_id)errid) + "): ", str, show_block);
152 82 }
153
154 static autoarray<labeldata> ldata;
155 static int labelsinldata = 0;
156 static autoarray<definedata> ddata;
157 static int definesinddata=0;
158
159 508 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 508 times.
698 for (int i=0;i<numprint;i++)
163 {
164 190 free_and_null(prints[i]);
165 }
166 508 prints.reset();
167 508 numprint=0;
168
169
2/2
✓ Branch 0 taken 382 times.
✓ Branch 1 taken 508 times.
890 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 508 errors.reset();
187 508 numerror=0;
188
189
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 508 times.
590 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 508 warnings.reset();
207 508 numwarn=0;
208
209
2/2
✓ Branch 0 taken 2265 times.
✓ Branch 1 taken 508 times.
2773 for (int i=0;i<definesinddata;i++)
210 {
211 2265 free_and_null(ddata[i].name);
212 2265 free_and_null(ddata[i].contents);
213 }
214 508 ddata.reset();
215 508 definesinddata=0;
216
217
2/2
✓ Branch 0 taken 363 times.
✓ Branch 1 taken 508 times.
871 for (int i=0;i<labelsinldata;i++)
218 363 free((void*)ldata[i].name);
219 508 ldata.reset();
220 508 labelsinldata=0;
221 #undef free_and_null
222
223 508 romCrc = 0;
224 508 clidefines.reset();
225 508 reset_warnings_to_default();
226
227 508 reseteverything();
228 508 }
229
230 #define maxromsize (16*1024*1024)
231
232 static bool expectsNewAPI = false;
233
234 363 static void addlabel(const string & name, const snes_label & label_data)
235 {
236 labeldata label;
237 363 label.name = strdup(name);
238 363 label.location = (int)(label_data.pos & 0xFFFFFF);
239
1/2
✓ Branch 0 taken 184 times.
✗ Branch 1 not taken.
363 ldata[labelsinldata++] = label;
240 363 }
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 503 static void asar_patch_begin(char * romdata_, int buflen, int * romlen_)
295 {
296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 503 times.
503 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 503 else romdata_r = (unsigned char*)romdata_;
302 503 romdata = (unsigned char*)malloc(maxromsize);
303 // RPG Hacker: Without this memset, freespace commands can (and probably will) fail.
304 503 memset((void*)romdata, 0, maxromsize);
305 503 memcpy(const_cast<unsigned char*>(romdata), romdata_, (size_t)*romlen_);
306 503 resetdllstuff();
307 503 romlen = *romlen_;
308 503 romlen_r = *romlen_;
309 503 }
310
311 503 static void asar_patch_main(const char * patchloc)
312 {
313
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 502 times.
503 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 1469 times.
✓ Branch 1 taken 483 times.
1952 for (pass = 0;pass < 3;pass++)
318 {
319
1/2
✓ Branch 0 taken 1469 times.
✗ Branch 1 not taken.
1469 initstuff();
320
2/2
✓ Branch 0 taken 1449 times.
✓ Branch 1 taken 20 times.
1469 assemblefile(patchloc);
321 // RPG Hacker: Necessary, because finishpass() can throws warning and errors.
322
2/4
✓ Branch 0 taken 1449 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 756 times.
✗ Branch 3 not taken.
2142 callstack_push cs_push(callstack_entry_type::FILE, filesystem->create_absolute_path(nullptr, patchloc));
323
1/2
✓ Branch 0 taken 1449 times.
✗ Branch 1 not taken.
1449 finishpass();
324 1449 }
325 }
326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 catch (errfatal&) {}
327 503 }
328
329 503 static bool asar_patch_end(char * romdata_, int buflen, int * romlen_)
330 {
331
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 251 times.
503 if (checksum_fix_enabled) fixchecksum();
332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 503 times.
503 if (romdata_ != (const char*)romdata_r) free(const_cast<unsigned char*>(romdata_r));
333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 503 times.
503 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 366 times.
503 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 366 times.
✗ Branch 1 not taken.
366 if (*romlen_ != buflen)
342 {
343 366 *romlen_ = romlen;
344 }
345 366 romCrc = crc32((const uint8_t*)romdata, (size_t)romlen);
346 366 memcpy(romdata_, romdata, (size_t)romlen);
347 366 free(const_cast<unsigned char*>(romdata));
348 366 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 177 EXPORT int asar_version()
368 {
369 177 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 503 EXPORT bool asar_patch(const struct patchparams_base *params)
415 {
416 503 auto execute_patch = [&]() {
417
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 503 times.
503 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 503 times.
503 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 503 memset(&paramscurrent, 0, sizeof(paramscurrent));
429 503 memcpy(&paramscurrent, params, (size_t)params->structsize);
430
431
432
1/2
✓ Branch 0 taken 262 times.
✗ Branch 1 not taken.
503 asar_patch_begin(paramscurrent.romdata, paramscurrent.buflen, paramscurrent.romlen);
433
434 503 simple_callstacks = !paramscurrent.full_call_stack;
435
436 262 autoarray<string> includepaths;
437 262 autoarray<const char*> includepath_cstrs;
438
439
2/2
✓ Branch 0 taken 244 times.
✓ Branch 1 taken 503 times.
747 for (int i = 0; i < paramscurrent.numincludepaths; ++i)
440 {
441
2/6
✓ Branch 0 taken 244 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 244 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
244 if (!path_is_absolute(paramscurrent.includepaths[i])) asar_throw_warning(pass, warning_id_relative_path_used, "include search");
442
2/4
✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 122 times.
✗ Branch 3 not taken.
244 string& newpath = includepaths.append(paramscurrent.includepaths[i]);
443
1/2
✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
244 includepath_cstrs.append((const char*)newpath);
444 }
445
446
2/2
✓ Branch 0 taken 245 times.
✓ Branch 1 taken 258 times.
503 if (paramscurrent.stdincludesfile != nullptr) {
447
2/6
✓ Branch 0 taken 245 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 245 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
245 if (!path_is_absolute(paramscurrent.stdincludesfile)) asar_throw_warning(pass, warning_id_relative_path_used, "std includes file");
448
1/2
✓ Branch 0 taken 123 times.
✗ Branch 1 not taken.
123 string stdincludespath = paramscurrent.stdincludesfile;
449
1/2
✓ Branch 0 taken 245 times.
✗ Branch 1 not taken.
245 parse_std_includes(stdincludespath, includepaths);
450 245 }
451
452
2/2
✓ Branch 0 taken 491 times.
✓ Branch 1 taken 503 times.
994 for (int i = 0; i < includepaths.count; ++i)
453 {
454
2/4
✓ Branch 0 taken 247 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 247 times.
✗ Branch 3 not taken.
491 includepath_cstrs.append((const char*)includepaths[i]);
455 }
456
457 503 size_t includepath_count = (size_t)includepath_cstrs.count;
458
1/2
✓ Branch 0 taken 262 times.
✗ Branch 1 not taken.
262 virtual_filesystem new_filesystem;
459
2/4
✓ Branch 0 taken 503 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 262 times.
✗ Branch 3 not taken.
503 new_filesystem.initialize(&includepath_cstrs[0], includepath_count);
460 503 filesystem = &new_filesystem;
461
462
2/2
✓ Branch 0 taken 269 times.
✓ Branch 1 taken 503 times.
772 for(int i = 0; i < paramscurrent.memory_file_count; ++i) {
463 269 memoryfile f = paramscurrent.memory_files[i];
464
1/2
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
269 filesystem->add_memory_file(f.path, f.buffer, f.length);
465 }
466
467 503 clidefines.reset();
468
2/2
✓ Branch 0 taken 978 times.
✓ Branch 1 taken 503 times.
1481 for (int i = 0; i < paramscurrent.additional_define_count; ++i)
469 {
470
2/4
✓ Branch 0 taken 978 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 490 times.
✗ Branch 3 not taken.
978 string name = (paramscurrent.additional_defines[i].name != nullptr ? paramscurrent.additional_defines[i].name : "");
471
1/2
✓ Branch 0 taken 490 times.
✗ Branch 1 not taken.
978 strip_whitespace(name);
472
1/2
✓ Branch 0 taken 490 times.
✗ Branch 1 not taken.
978 name.strip_prefix('!'); // remove leading ! if present
473
2/6
✓ Branch 0 taken 978 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 978 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
978 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 490 times.
✓ Branch 1 taken 488 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 490 times.
978 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 734 times.
✓ Branch 1 taken 244 times.
✓ Branch 2 taken 490 times.
✗ Branch 3 not taken.
978 string contents = (paramscurrent.additional_defines[i].contents != nullptr ? paramscurrent.additional_defines[i].contents : "");
479
2/4
✓ Branch 0 taken 978 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 490 times.
✗ Branch 3 not taken.
978 clidefines.create(name) = contents;
480
1/2
✓ Branch 0 taken 490 times.
✗ Branch 1 not taken.
978 }
481
482
2/2
✓ Branch 0 taken 245 times.
✓ Branch 1 taken 258 times.
503 if (paramscurrent.stddefinesfile != nullptr) {
483
2/6
✓ Branch 0 taken 245 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 245 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
245 if (!path_is_absolute(paramscurrent.stddefinesfile)) asar_throw_warning(pass, warning_id_relative_path_used, "std defines file");
484
1/2
✓ Branch 0 taken 123 times.
✗ Branch 1 not taken.
123 string stddefinespath = paramscurrent.stddefinesfile;
485
1/2
✓ Branch 0 taken 245 times.
✗ Branch 1 not taken.
245 parse_std_defines(stddefinespath);
486 245 } else {
487
1/2
✓ Branch 0 taken 258 times.
✗ Branch 1 not taken.
258 parse_std_defines(nullptr); // needed to populate builtin defines
488 }
489
490
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 503 times.
505 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 239 times.
✓ Branch 1 taken 264 times.
503 if(paramscurrent.override_checksum_gen) {
505 239 checksum_fix_enabled = paramscurrent.generate_checksum;
506 239 force_checksum_fix = true;
507 }
508
509
1/2
✓ Branch 0 taken 503 times.
✗ Branch 1 not taken.
503 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 503 times.
✗ Branch 1 not taken.
503 closecachedfiles();
514
515
1/2
✓ Branch 0 taken 503 times.
✗ Branch 1 not taken.
503 new_filesystem.destroy();
516 503 filesystem = nullptr;
517
518
1/2
✓ Branch 0 taken 503 times.
✗ Branch 1 not taken.
503 return asar_patch_end(paramscurrent.romdata, paramscurrent.buflen, paramscurrent.romlen);
519 503 };
520 #if defined(RUN_VIA_FIBER)
521 241 return run_as_fiber(execute_patch);
522 #elif defined(RUN_VIA_THREAD)
523
1/2
✓ Branch 0 taken 262 times.
✗ Branch 1 not taken.
524 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 218 EXPORT int asar_maxromsize()
536 {
537 218 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 499 EXPORT const struct errordata * asar_geterrors(int * count)
547 {
548 499 *count=numerror;
549 499 return errors;
550 }
551
552 /* $EXPORT$
553 * Get a list of all warnings.
554 */
555 499 EXPORT const struct errordata * asar_getwarnings(int * count)
556 {
557 499 *count=numwarn;
558 499 return warnings;
559 }
560
561 /* $EXPORT$
562 * Get a list of all printed data.
563 */
564 483 EXPORT const char * const * asar_getprints(int * count)
565 {
566 483 *count=numprint;
567 483 return prints;
568 }
569
570 /* $EXPORT$
571 * Get a list of all labels.
572 */
573 177 EXPORT const struct labeldata * asar_getalllabels(int * count)
574 {
575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 177 times.
177 for (int i=0;i<labelsinldata;i++) free((void*)ldata[i].name);
576 177 labelsinldata=0;
577 177 labels.each(addlabel);
578 177 *count=labelsinldata;
579 177 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 178 EXPORT const char * asar_getdefine(const char * name)
600 {
601
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 89 times.
178 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 2265 static void adddef(const string& name, string& value)
620 {
621 definedata define;
622 2265 define.name= duplicate_string(name);
623 2265 define.contents= duplicate_string(value);
624
1/2
✓ Branch 0 taken 1141 times.
✗ Branch 1 not taken.
2265 ddata[definesinddata++]=define;
625 2265 }
626
627 /* $EXPORT$
628 * Gets the values and names of all defines.
629 */
630 179 EXPORT const struct definedata * asar_getalldefines(int * count)
631 {
632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 179 times.
179 for (int i=0;i<definesinddata;i++)
633 {
634 free((void*)ddata[i].name);
635 free((void*)ddata[i].contents);
636 }
637 179 definesinddata=0;
638 179 defines.each(adddef);
639 179 *count=definesinddata;
640 179 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 176 EXPORT double asar_math(const char * math_, const char ** error)
651 {
652 88 ns="";
653 176 namespace_list.reset();
654 176 sublabels.reset();
655 176 errored=false;
656 176 ismath=true;
657 176 initmathcore();
658 88 double rval=0;
659 try
660 {
661
1/2
✓ Branch 0 taken 176 times.
✗ Branch 1 not taken.
176 rval=(double)math(math_);
662 }
663 catch(errfatal&)
664 {
665 *error=matherror;
666 }
667 176 ismath=false;
668 176 deinitmathcore();
669 176 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 178 EXPORT const struct writtenblockdata * asar_getwrittenblocks(int * count)
677 {
678 178 *count = writtenblocks.count;
679 178 return writtenblocks;
680 }
681
682 /* $EXPORT$
683 * Get the mapper currently used by Asar.
684 */
685 184 EXPORT enum mapper_t asar_getmapper()
686 {
687 184 return mapper;
688 }
689
690 /* $EXPORT$
691 * Generates the contents of a symbols file for in a specific format.
692 */
693 176 EXPORT const char * asar_getsymbolsfile(const char* type){
694
3/6
✓ Branch 0 taken 176 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 88 times.
✗ Branch 5 not taken.
176 symbolsfile = create_symbols_file(type, romCrc);
695 176 return symbolsfile;
696 }
697
698 #if defined(__clang__)
699 # pragma clang diagnostic pop
700 #endif
701