asar coverage - build #176


src/asar/
File: src/asar/main.cpp
Date: 2024-01-28 18:24:31
Lines:
460/561
82.0%
Functions:
19/22
86.4%
Branches:
536/905
59.2%

Line Branch Exec Source
1 // "because satanism is best defeated by summoning a bigger satan"
2 // ~Alcaro, 2019 (discussing Asar)
3 #include "addr2line.h"
4 #include "std-includes.h"
5 #include "libsmw.h"
6 #include "libstr.h"
7 #include "assocarr.h"
8 #include "autoarray.h"
9 #include "asar.h"
10 #include "virtualfile.h"
11 #include "warnings.h"
12 #include "platform/file-helpers.h"
13 #include "assembleblock.h"
14 #include "asar_math.h"
15 #include "macro.h"
16 #include <cstdint>
17
18 // randomdude999: remember to also update the .rc files (in res/windows/) when changing this.
19 // Couldn't find a way to automate this without shoving the version somewhere in the CMake files
20 const int asarver_maj=1;
21 const int asarver_min=9;
22 const int asarver_bug=0;
23 const bool asarver_beta=true;
24 bool default_math_pri=false;
25 bool default_math_round_off=false;
26 extern bool suppress_all_warnings;
27
28 #ifdef _I_RELEASE
29 extern char blockbetareleases[(!asarver_beta)?1:-1];
30 #endif
31 #ifdef _I_DEBUG
32 extern char blockreleasedebug[(asarver_beta)?1:-1];
33 #endif
34
35 unsigned const char * romdata_r;
36 int romlen_r;
37
38 int pass;
39
40 int optimizeforbank=-1;
41 int optimize_dp = optimize_dp_flag::NONE;
42 int dp_base = 0;
43 int optimize_address = optimize_address_flag::DEFAULT;
44
45 string thisfilename;
46 int thisline;
47 const char * thisblock;
48
49 string callerfilename;
50 int callerline=-1;
51
52 bool errored=false;
53 bool ignoretitleerrors=false;
54
55 volatile int recursioncount=0;
56
57 virtual_filesystem* filesystem = nullptr;
58
59 AddressToLineMapping addressToLineMapping;
60
61 99 int get_version_int()
62 {
63 99 return asarver_maj * 10000 + asarver_min * 100 + asarver_bug;
64 }
65
66 56 bool setmapper()
67 {
68 28 int maxscore=-99999;
69 28 mapper_t bestmap=lorom;
70 56 mapper_t maps[]={lorom, hirom, exlorom, exhirom};
71
2/2
✓ Branch 0 taken 224 times.
✓ Branch 1 taken 56 times.
280 for (size_t mapid=0;mapid<sizeof(maps)/sizeof(maps[0]);mapid++)
72 {
73 224 mapper=maps[mapid];
74 112 int score=0;
75 112 int highbits=0;
76 112 bool foundnull=false;
77
2/2
✓ Branch 0 taken 4704 times.
✓ Branch 1 taken 224 times.
4928 for (int i=0;i<21;i++)
78 {
79 4704 unsigned char c=romdata[snestopc(0x00FFC0+i)];
80
3/4
✓ Branch 0 taken 1700 times.
✓ Branch 1 taken 3004 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1700 times.
4704 if (foundnull && c) score-=4;//according to some documents, NUL terminated names are possible - but they shouldn't appear in the middle of the name
81
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4704 times.
4704 if (c>=128) highbits++;
82
2/2
✓ Branch 0 taken 810 times.
✓ Branch 1 taken 3894 times.
4704 else if (is_upper(c)) score+=3;
83
2/2
✓ Branch 0 taken 324 times.
✓ Branch 1 taken 3570 times.
3894 else if (c==' ') score+=2;
84
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3570 times.
3570 else if (is_digit(c)) score+=1;
85
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3570 times.
3570 else if (is_lower(c)) score+=1;
86
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3570 times.
3570 else if (c=='-') score+=1;
87
2/2
✓ Branch 0 taken 1785 times.
✓ Branch 1 taken 1785 times.
3570 else if (!c) foundnull=true;
88 else score-=3;
89 }
90
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 224 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
224 if (highbits>0 && highbits<=14) score-=21;//high bits set on some, but not all, bytes = unlikely to be a ROM
91
4/4
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 168 times.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 28 times.
252 if ((romdata[snestopc(0x00FFDE)]^romdata[snestopc(0x00FFDC)])!=0xFF ||
92
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
140 (romdata[snestopc(0x00FFDF)]^romdata[snestopc(0x00FFDD)])!=0xFF) score=-99999;//checksum doesn't match up to 0xFFFF? Not a ROM.
93 //too lazy to check the real checksum
94
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 168 times.
224 if (score>maxscore)
95 {
96 28 maxscore=score;
97 28 bestmap=mapper;
98 }
99 }
100 56 mapper=bestmap;
101
102 //detect oddball mappers
103 56 int mapperbyte=romdata[snestopc(0x00FFD5)];
104 56 int romtypebyte=romdata[snestopc(0x00FFD6)];
105
1/2
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
56 if (mapper==lorom)
106 {
107
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
56 if (mapperbyte==0x23 && (romtypebyte==0x32 || romtypebyte==0x34 || romtypebyte==0x35)) mapper=sa1rom;
108 }
109 56 return (maxscore>=0);
110 }
111
112 190 string getdecor()
113 {
114 95 string e;
115
2/4
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
190 if (thisfilename)
116 {
117
2/4
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
190 e+=STR thisfilename;
118
5/10
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 95 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 95 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 95 times.
✗ Branch 9 not taken.
285 if (thisline!=-1) e+=STR ":"+dec(thisline+1);
119
11/18
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 81 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 81 times.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 14 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 14 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 14 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 14 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 14 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 14 times.
✗ Branch 17 not taken.
204 if (callerfilename) e+=STR" (called from "+callerfilename+":"+dec(callerline+1)+")";
120
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
190 e+=": ";
121 }
122 190 return e;
123 }
124
125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
6 asar_error_id vfile_error_to_error_id(virtual_file_error vfile_error)
126 {
127
1/5
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
3 switch (vfile_error)
128 {
129 case vfe_doesnt_exist:
130 return error_id_file_not_found;
131 case vfe_access_denied:
132 return error_id_failed_to_open_file_access_denied;
133 3 case vfe_not_regular_file:
134 3 return error_id_failed_to_open_not_regular_file;
135 case vfe_unknown:
136 case vfe_none:
137 case vfe_num_errors:
138 return error_id_failed_to_open_file;
139 }
140
141 return error_id_failed_to_open_file;
142 }
143
144 6 virtual_file_error asar_get_last_io_error()
145 {
146
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (filesystem != nullptr)
147 {
148 6 return filesystem->get_last_error();
149 }
150
151 return vfe_unknown;
152 }
153
154 static bool freespaced;
155 632 static int getlenforlabel(int insnespos, int thislabel, bool exists)
156 {
157
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 632 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
632 if (warnxkas && (((unsigned int)(thislabel^insnespos)&0xFFFF0000)==0))
158 asar_throw_warning(1, warning_id_xkas_label_access);
159 632 unsigned int bank = thislabel>>16;
160 632 unsigned int word = thislabel&0xFFFF;
161 unsigned int relaxed_bank;
162
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 626 times.
632 if(optimizeforbank >= 0) {
163 6 relaxed_bank = optimizeforbank;
164 } else {
165
2/2
✓ Branch 0 taken 506 times.
✓ Branch 1 taken 120 times.
626 if((insnespos & 0xff000000) == 0) {
166 506 relaxed_bank = insnespos >> 16;
167 } else {
168
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 60 times.
120 if(freespace_is_freecode) relaxed_bank = 0;
169 18 else relaxed_bank = 0x40;
170 }
171 }
172
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 552 times.
632 if (!exists)
173 {
174
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 10 times.
80 if (!freespaced) freespaceextra++;
175 80 freespaced=true;
176 80 return 2;
177 }
178
6/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 540 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 3 times.
552 else if((optimize_dp == optimize_dp_flag::RAM) && bank == 0x7E && (word-dp_base < 0x100))
179 {
180 3 return 1;
181 }
182
6/8
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 528 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9 times.
✓ Branch 7 taken 9 times.
546 else if(optimize_dp == optimize_dp_flag::ALWAYS && (bank == 0x7E || !(bank & 0x40)) && (word-dp_base < 0x100))
183 {
184 6 return 1;
185 }
186 534 else if (
187 // if we should optimize ram accesses...
188
4/4
✓ Branch 0 taken 296 times.
✓ Branch 1 taken 238 times.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 220 times.
534 (optimize_address == optimize_address_flag::RAM || optimize_address == optimize_address_flag::MIRRORS)
189 // and we're in a bank with ram mirrors... (optimizeforbank=0x7E is checked later)
190
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 18 times.
94 && !(relaxed_bank & 0x40)
191 // and the label is in low RAM
192
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
76 && bank == 0x7E && word < 0x2000)
193 {
194 9 return 2;
195 }
196
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 232 times.
516 else if (
197 // if we should optimize mirrors...
198
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 232 times.
258 optimize_address == optimize_address_flag::MIRRORS
199 // we're in a bank with ram mirrors...
200
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 12 times.
52 && !(relaxed_bank & 0x40)
201 // and the label is in a mirrored section
202
3/4
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 22 times.
40 && !(bank & 0x40) && word < 0x8000)
203 {
204 9 return 2;
205 }
206
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 494 times.
498 else if (optimizeforbank>=0)
207 {
208 // if optimizing for a specific bank:
209 // if the label is in freespace, never optimize
210
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if ((unsigned int)thislabel&0xFF000000) return 3;
211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 else if (bank==(unsigned int)optimizeforbank) return 2;
212 2 else return 3;
213 }
214
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 396 times.
494 else if ((unsigned int)(thislabel|insnespos)&0xFF000000)
215 {
216 // optimize only if the label is in the same freespace
217
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 49 times.
98 if ((unsigned int)(thislabel^insnespos)&0xFF000000) return 3;
218 10 else return 2;
219 }
220
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 198 times.
396 else if ((thislabel^insnespos)&0xFF0000){ return 3; }
221 185 else { return 2;}
222 }
223
224
225 3318 bool is_hex_constant(const char* str){
226
2/2
✓ Branch 0 taken 2732 times.
✓ Branch 1 taken 586 times.
3318 if (*str=='$')
227 {
228 2732 str++;
229
2/2
✓ Branch 0 taken 9540 times.
✓ Branch 1 taken 2732 times.
12272 while(is_xdigit(*str)) {
230 9540 str++;
231 }
232
2/2
✓ Branch 0 taken 1366 times.
✓ Branch 1 taken 1366 times.
2732 if(*str=='\0'){
233 1366 return true;
234 }
235 }
236 293 return false;
237 }
238
239 3060 int getlen(const char * orgstr, bool optimizebankextraction)
240 {
241 3060 const char * str=orgstr;
242 3060 freespaced=false;
243
244 3060 const char* posneglabel = str;
245
1/2
✓ Branch 0 taken 1530 times.
✗ Branch 1 not taken.
3060 string posnegname = posneglabelname(&posneglabel, false);
246
247
4/4
✓ Branch 0 taken 3027 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 1497 times.
✓ Branch 3 taken 33 times.
3060 if (posnegname.length() > 0)
248 {
249
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 60 times.
66 if (*posneglabel != '\0') goto notposneglabel;
250
251
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 30 times.
80 if (!pass) return 2;
252 20 snes_label label_data;
253 // RPG Hacker: Umm... what kind of magic constant is this?
254 40 label_data.pos = 31415926;
255
2/4
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
40 bool found = labelval(posnegname, &label_data);
256
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 return getlenforlabel(snespos, (int)label_data.pos, found);
257 }
258 2997 notposneglabel:
259 1500 int len=0;
260
2/2
✓ Branch 0 taken 3146 times.
✓ Branch 1 taken 3000 times.
6146 while (*str)
261 {
262 1573 int thislen=0;
263 3146 bool maybebankextraction=(str==orgstr);
264
2/2
✓ Branch 0 taken 2324 times.
✓ Branch 1 taken 822 times.
3146 if (*str=='$')
265 {
266 2324 str++;
267 int i;
268
2/2
✓ Branch 0 taken 9060 times.
✓ Branch 1 taken 2324 times.
11384 for (i=0;is_xdigit(str[i]);i++);
269 //if (i&1) warn(S dec(i)+"-digit hex value");//blocked in getnum instead
270 2324 thislen=(i+1)/2;
271 2324 str+=i;
272 }
273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 822 times.
822 else if (*str=='%')
274 {
275 str++;
276 int i;
277 for (i=0;str[i]=='0' || str[i]=='1';i++);
278 //if (i&7) warn(S dec(i)+"-digit binary value");
279 thislen=(i+7)/8;
280 str+=i;
281 }
282
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 822 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
822 else if (str[0]=='\'' && str[2]=='\'')
283 {
284 thislen=1;
285 str+=3;
286 }
287
2/2
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 698 times.
822 else if (is_digit(*str))
288 {
289 124 int val=strtol(str, const_cast<char**>(&str), 10);
290
1/2
✓ Branch 0 taken 124 times.
✗ Branch 1 not taken.
124 if (val>=0) thislen=1;
291
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 62 times.
124 if (val>=256) thislen=2;
292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (val>=65536) thislen=3;
293
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 if (val>=16777216) thislen=4;
294 }
295
7/10
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 592 times.
✓ Branch 2 taken 53 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 53 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 53 times.
✓ Branch 8 taken 296 times.
✓ Branch 9 taken 53 times.
698 else if (is_alpha(*str) || *str=='_' || *str=='.' || *str=='?')
296 {
297 296 snes_label thislabel;
298
1/2
✓ Branch 0 taken 592 times.
✗ Branch 1 not taken.
592 bool exists=labelval(&str, &thislabel);
299
1/2
✓ Branch 0 taken 592 times.
✗ Branch 1 not taken.
592 thislen=getlenforlabel(snespos, (int)thislabel.pos, exists);
300 }
301 106 else str++;
302
4/4
✓ Branch 0 taken 398 times.
✓ Branch 1 taken 2748 times.
✓ Branch 2 taken 164 times.
✓ Branch 3 taken 70 times.
3146 if (optimizebankextraction && maybebankextraction &&
303
4/6
✓ Branch 0 taken 328 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 328 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 164 times.
✓ Branch 5 taken 164 times.
328 (!strcmp(str, ">>16") || !strcmp(str, "/65536") || !strcmp(str, "/$10000")))
304 return 1;
305
2/2
✓ Branch 0 taken 1508 times.
✓ Branch 1 taken 65 times.
1573 if (thislen>len) len=thislen;
306 }
307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1500 times.
3000 if (len>3) return 3;
308 1500 return len;
309 3060 }
310
311 struct strcompare {
312 bool operator() (const char * lhs, const char * rhs) const
313 {
314 return strcmp(lhs, rhs)<0;
315 }
316 };
317
318 struct stricompare {
319 bool operator() (const char * lhs, const char * rhs) const
320 {
321 return stricmp(lhs, rhs)<0;
322 }
323 };
324
325 struct sourcefile {
326 char** contents;
327 int numlines;
328 };
329
330 static assocarr<sourcefile> filecontents;
331 assocarr<string> defines;
332 // needs to be separate because defines is reset between parsing arguments and patching
333 assocarr<string> clidefines;
334 assocarr<string> builtindefines;
335
336 1776 bool validatedefinename(const char * name)
337 {
338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1776 times.
1776 if (!name[0]) return false;
339
2/2
✓ Branch 0 taken 17886 times.
✓ Branch 1 taken 1776 times.
19662 for (int i = 0;name[i];i++)
340 {
341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17886 times.
17886 if (!is_ualnum(name[i])) return false;
342 }
343
344 888 return true;
345 }
346
347 1507430 void resolvedefines(string& out, const char * start)
348 {
349
2/2
✓ Branch 0 taken 753714 times.
✓ Branch 1 taken 1 times.
753715 recurseblock rec;
350 753714 const char * here=start;
351
2/2
✓ Branch 0 taken 8620940 times.
✓ Branch 1 taken 1507416 times.
10128356 while (*here)
352 {
353
4/4
✓ Branch 0 taken 3126 times.
✓ Branch 1 taken 8617814 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 3114 times.
8620940 if (*here=='"' && emulatexkas)
354 {
355
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 asar_throw_warning(0, warning_id_feature_deprecated, "xkas define quotes", "removing the quotes generally does what you want");
356
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
12 out+=*here++;
357
5/6
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 6 times.
48 while (*here && *here!='"') out+=*here++;
358
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
12 out+=*here++;
359 }
360
4/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 8620880 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 42 times.
8620928 else if (here[0] == '\\' && here[1] == '\\')
361 {
362 // allow using \\ as escape sequence
363
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 out += "\\";
364 6 here += 2;
365 }
366
4/4
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 8620880 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 12 times.
8620922 else if (here[0] == '\\' && here[1] == '!')
367 {
368 // allow using \! to escape !
369
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
30 out+="!";
370 30 here += 2;
371 }
372
2/2
✓ Branch 0 taken 635196 times.
✓ Branch 1 taken 7985696 times.
8620892 else if (*here=='!')
373 {
374
7/10
✓ Branch 0 taken 212796 times.
✓ Branch 1 taken 422400 times.
✓ Branch 2 taken 211236 times.
✓ Branch 3 taken 1560 times.
✓ Branch 4 taken 211038 times.
✓ Branch 5 taken 198 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 211038 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
635196 bool first=(here==start || (here>=start+4 && here[-1]==' ' && here[-2]==':' && here[-3]==' '));//check if it's the start of a block
375 317598 string defname;
376 635196 here++;
377
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 635088 times.
635196 if (*here=='{')
378 {
379 108 here++;
380 54 string unprocessedname;
381 54 int braces=1;
382 while (true)
383 {
384
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 1080 times.
1152 if (*here=='{') braces++;
385
2/2
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 972 times.
1152 if (*here=='}') braces--;
386
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1152 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1152 if (!*here) asar_throw_error(0, error_type_line, error_id_mismatched_braces);
387
2/2
✓ Branch 0 taken 576 times.
✓ Branch 1 taken 576 times.
1152 if (!braces) break;
388
1/2
✓ Branch 0 taken 522 times.
✗ Branch 1 not taken.
1044 unprocessedname+=*here++;
389 }
390
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
108 here++;
391
1/2
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
108 resolvedefines(defname, unprocessedname);
392
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
108 if (!validatedefinename(defname)) asar_throw_error(0, error_type_line, error_id_invalid_define_name);
393 108 }
394 else
395 {
396
4/4
✓ Branch 0 taken 654816 times.
✓ Branch 1 taken 317544 times.
✓ Branch 2 taken 327408 times.
✓ Branch 3 taken 317544 times.
1289904 while (is_ualnum(*here)) defname+=*here++;
397 }
398
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 635196 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
635196 if (warnxkas && here[0]=='(' && here[1]==')')
399 asar_throw_warning(0, warning_id_xkas_eat_parentheses);
400 //if (emulatexkas && here[0]=='(' && here[1]==')') here+=2;
401
402
2/2
✓ Branch 0 taken 317598 times.
✓ Branch 1 taken 317598 times.
635196 if (first)
403 {
404 enum {
405 null,
406 append,
407 expand,
408 domath,
409 setifnotset,
410 } mode;
411 if(0);
412
2/2
✓ Branch 0 taken 270 times.
✓ Branch 1 taken 422130 times.
422400 else if (stribegin(here, " = ")) { here+=3; mode=null; }
413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 422130 times.
422130 else if (stribegin(here, " += ")) { here+=4; mode=append; }
414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 422130 times.
422130 else if (stribegin(here, " := ")) { here+=4; mode=expand; }
415
2/2
✓ Branch 0 taken 210966 times.
✓ Branch 1 taken 211164 times.
422130 else if (stribegin(here, " #= ")) { here+=4; mode=domath; }
416
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 211158 times.
211164 else if (stribegin(here, " ?= ")) { here+=4; mode=setifnotset; }
417 211158 else goto notdefineset;
418
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 211242 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
211242 if (emulatexkas && mode != null) asar_throw_warning(0, warning_id_convert_to_asar);
419 //else if (stribegin(here, " equ ")) here+=5;
420 105621 string val;
421
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 211200 times.
211242 if (*here=='"')
422 {
423 42 here++;
424 while (true)
425 {
426
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 147 times.
294 if (*here=='"')
427 {
428
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
48 if (!here[1] || here[1]==' ') break;
429
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 else if (here[1]=='"') here++;
430 else asar_throw_error(0, error_type_line, error_id_broken_define_declaration);
431 }
432
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
252 val+=*here++;
433 }
434 42 here++;
435 }
436 else
437 {
438
5/6
✓ Branch 0 taken 848736 times.
✓ Branch 1 taken 105600 times.
✓ Branch 2 taken 848736 times.
✓ Branch 3 taken 105600 times.
✓ Branch 4 taken 424368 times.
✗ Branch 5 not taken.
1059936 while (*here && *here!=' ') val+=*here++;
439 }
440 //if (strqchr(val.data(), ';')) *strqchr(val.data(), ';')=0;
441
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 211242 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 105621 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
211242 if (*here && !stribegin(here, " : ")) asar_throw_error(0, error_type_line, error_id_broken_define_declaration);
442
4/8
✓ Branch 0 taken 211242 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 211242 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 211242 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 211242 times.
✗ Branch 7 not taken.
211242 clean(val);
443
444 // RPG Hacker: throw an error if we're trying to overwrite built-in defines.
445
4/4
✓ Branch 0 taken 105624 times.
✓ Branch 1 taken 105618 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 105618 times.
211242 if (builtindefines.exists(defname))
446 {
447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 asar_throw_error(0, error_type_line, error_id_overriding_builtin_define, defname.data());
448 }
449
450
3/6
✓ Branch 0 taken 264 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 210966 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
211236 switch (mode)
451 {
452 132 case null:
453 {
454
2/4
✓ Branch 0 taken 264 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 132 times.
✗ Branch 3 not taken.
264 defines.create(defname) = val;
455 132 break;
456 }
457 case append:
458 {
459 if (!defines.exists(defname)) asar_throw_error(0, error_type_line, error_id_define_not_found, defname.data());
460 string oldval = defines.find(defname);
461 val=oldval+val;
462 defines.create(defname) = val;
463 break;
464 }
465 case expand:
466 {
467 string newval;
468 resolvedefines(newval, val);
469 defines.create(defname) = newval;
470 break;
471 }
472 105483 case domath:
473 {
474 105483 string newval;
475
1/2
✓ Branch 0 taken 210966 times.
✗ Branch 1 not taken.
210966 resolvedefines(newval, val);
476
1/2
✓ Branch 0 taken 210966 times.
✗ Branch 1 not taken.
210966 double num= getnumdouble(newval);
477
5/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 210954 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
210966 if (foundlabel && !foundlabel_static) asar_throw_error(0, error_type_line, error_id_define_label_math);
478
3/6
✓ Branch 0 taken 210960 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 105480 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 105480 times.
✗ Branch 5 not taken.
210960 defines.create(defname) = ftostr(num);
479 105480 break;
480 210966 }
481 3 case setifnotset:
482 {
483
4/8
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
6 if (!defines.exists(defname)) defines.create(defname) = val;
484 3 break;
485 }
486 }
487 211242 }
488 else
489 {
490 318375 notdefineset:
491
5/6
✓ Branch 0 taken 211995 times.
✓ Branch 1 taken 211959 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 211959 times.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
423954 if (!defname) out+="!";
492 else
493 {
494
3/6
✓ Branch 0 taken 211959 times.
✓ Branch 1 taken 211959 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 211959 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
423918 if (!defines.exists(defname)) asar_throw_error(0, error_type_line, error_id_define_not_found, defname.data());
495 else {
496
2/4
✓ Branch 0 taken 211959 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 211959 times.
✗ Branch 3 not taken.
423918 string thisone = defines.find(defname);
497
1/2
✓ Branch 0 taken 423918 times.
✗ Branch 1 not taken.
423918 resolvedefines(out, thisone);
498 423918 }
499 }
500 }
501 635196 }
502
1/2
✓ Branch 0 taken 3992848 times.
✗ Branch 1 not taken.
7985696 else out+=*here++;
503 }
504 2261136 }
505
506 int repeatnext=1;
507
508 bool moreonline;
509 bool moreonlinecond;
510 int fakeendif;
511 bool asarverallowed;
512 bool istoplevel;
513
514 873824 void assembleline(const char * fname, int linenum, const char * line)
515 {
516
1/2
✓ Branch 0 taken 436912 times.
✗ Branch 1 not taken.
436912 recurseblock rec;
517 873824 bool moreonlinetmp=moreonline;
518 // randomdude999: redundant, assemblefile already converted the path to absolute
519 //string absolutepath = filesystem->create_absolute_path("", fname);
520
1/2
✓ Branch 0 taken 436912 times.
✗ Branch 1 not taken.
436912 string absolutepath = fname;
521
1/2
✓ Branch 0 taken 436912 times.
✗ Branch 1 not taken.
436912 thisfilename = absolutepath;
522 873824 thisline=linenum;
523 873824 thisblock= nullptr;
524 873824 single_line_for_tracker = 1;
525 try
526 {
527 436912 string tmp;
528
7/8
✓ Branch 0 taken 1032 times.
✓ Branch 1 taken 872792 times.
✓ Branch 2 taken 948 times.
✓ Branch 3 taken 84 times.
✓ Branch 4 taken 906 times.
✓ Branch 5 taken 42 times.
✓ Branch 6 taken 453 times.
✗ Branch 7 not taken.
873824 if(inmacro && numif == numtrue) tmp = replace_macro_args(line);
529
1/2
✓ Branch 0 taken 436438 times.
✗ Branch 1 not taken.
436438 else tmp = line;
530
4/8
✓ Branch 0 taken 873782 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 873782 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 873782 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 873782 times.
✗ Branch 7 not taken.
873782 clean(tmp);
531 436891 string out;
532
4/4
✓ Branch 0 taken 872108 times.
✓ Branch 1 taken 1674 times.
✓ Branch 2 taken 872094 times.
✓ Branch 3 taken 14 times.
873782 if (numif==numtrue) resolvedefines(out, tmp);
533
1/2
✓ Branch 0 taken 837 times.
✗ Branch 1 not taken.
837 else out=tmp;
534 // recheck quotes - defines can mess those up sometimes
535
4/6
✓ Branch 0 taken 873768 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 873762 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
873768 if (!confirmquotes(out)) asar_throw_error(0, error_type_line, error_id_mismatched_quotes);
536
1/2
✓ Branch 0 taken 873762 times.
✗ Branch 1 not taken.
873762 out.qreplace(": :", ": :", true);
537 //puts(out);
538
1/2
✓ Branch 0 taken 873762 times.
✗ Branch 1 not taken.
873762 autoptr<char**> blocks=qsplit(out.temp_raw(), " : ");
539 873762 moreonline=true;
540 873762 moreonlinecond=true;
541 873762 fakeendif=0;
542
2/2
✓ Branch 0 taken 875376 times.
✓ Branch 1 taken 873262 times.
1748638 for (int block=0;moreonline;block++)
543 {
544 875376 moreonline=(blocks[block+1] != nullptr);
545 875376 int repeatthis=repeatnext;
546 875376 repeatnext=1;
547
2/2
✓ Branch 0 taken 875376 times.
✓ Branch 1 taken 874876 times.
1750252 for (int i=0;i<repeatthis;i++)
548 {
549 try
550 {
551
1/2
✓ Branch 0 taken 437688 times.
✗ Branch 1 not taken.
875376 string stripped_block = blocks[block];
552
1/2
✓ Branch 0 taken 875376 times.
✗ Branch 1 not taken.
875376 strip_both(stripped_block, ' ', true);
553
554
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 437682 times.
875376 thisline=linenum;//do not optimize, this one is recursive
555 875376 thisblock = stripped_block.data();
556 437688 bool isspecialline = false;
557
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 875364 times.
875376 if (thisblock[0] == '@')
558 {
559
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 asar_throw_warning(0, warning_id_feature_deprecated, "prefixing Asar commands with @ or ;@", "remove the @ or ;@ prefix");
560
561 6 isspecialline = true;
562 12 thisblock++;
563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 while (is_space(*thisblock))
564 {
565 thisblock++;
566 }
567 }
568
2/2
✓ Branch 0 taken 874716 times.
✓ Branch 1 taken 660 times.
875376 assembleblock(thisblock, isspecialline);
569
2/2
✓ Branch 0 taken 874714 times.
✓ Branch 1 taken 2 times.
874716 checkbankcross();
570 875376 }
571
2/2
✓ Branch 0 taken 500 times.
✓ Branch 1 taken 162 times.
662 catch (errblock&) {}
572
6/6
✓ Branch 0 taken 653118 times.
✓ Branch 1 taken 221758 times.
✓ Branch 2 taken 653106 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 326553 times.
✓ Branch 5 taken 110885 times.
874876 if (blocks[block][0]!='\0' && blocks[block][0]!='@') asarverallowed=false;
573 }
574
2/2
✓ Branch 0 taken 872854 times.
✓ Branch 1 taken 2022 times.
874876 if(single_line_for_tracker == 1) single_line_for_tracker = 0;
575 }
576
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 873262 times.
873262 if(fakeendif)
577 {
578 thisline = linenum;
579 thisblock = blocks[0];
580 asar_throw_warning(0, warning_id_feature_deprecated, "inline if statements", "Add an \" : endif\" at the end of the line");
581 if (numif==numtrue) numtrue--;
582 numif--;
583 }
584 874844 }
585
2/2
✓ Branch 0 taken 502 times.
✓ Branch 1 taken 60 times.
562 catch (errline&) {}
586 873322 moreonline=moreonlinetmp;
587 1310987 }
588
589 int incsrcdepth=0;
590
591 // Returns true if a file is protected via
592 // an "includeonce".
593 1234 bool file_included_once(const char* file)
594 {
595
2/2
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 1192 times.
1432 for (int i = 0; i < includeonce.count; ++i)
596 {
597
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 120 times.
240 if (includeonce[i] == file)
598 {
599 21 return true;
600 }
601 }
602
603 596 return false;
604 }
605
606 1204 void assemblefile(const char * filename, bool toplevel)
607 {
608 1204 incsrcdepth++;
609
1/2
✓ Branch 0 taken 602 times.
✗ Branch 1 not taken.
1204 string absolutepath = filesystem->create_absolute_path(thisfilename, filename);
610
611
4/4
✓ Branch 0 taken 1183 times.
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 581 times.
1204 if (file_included_once(absolutepath))
612 {
613 21 return;
614 }
615
616
1/2
✓ Branch 0 taken 581 times.
✗ Branch 1 not taken.
581 string prevthisfilename = thisfilename;
617
1/2
✓ Branch 0 taken 581 times.
✗ Branch 1 not taken.
581 thisfilename = absolutepath;
618 1162 int prevline = thisline;
619 1162 thisline=-1;
620 1162 const char* prevthisblock = thisblock;
621 1162 thisblock= nullptr;
622 581 sourcefile file;
623 1162 file.contents = nullptr;
624 1162 file.numlines = 0;
625
2/2
✓ Branch 0 taken 114 times.
✓ Branch 1 taken 467 times.
1162 int startif=numif;
626
4/4
✓ Branch 0 taken 695 times.
✓ Branch 1 taken 467 times.
✓ Branch 2 taken 114 times.
✓ Branch 3 taken 467 times.
1162 if (!filecontents.exists(absolutepath))
627 {
628
1/2
✓ Branch 0 taken 228 times.
✗ Branch 1 not taken.
228 char * temp= readfile(absolutepath, "");
629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 228 times.
228 if (!temp)
630 {
631 // RPG Hacker: This is so that we hopefully always end up with a proper decor
632 // and get better error messages.
633 thisfilename = prevthisfilename;
634 thisline = prevline;
635 thisblock = prevthisblock;
636
637 asar_throw_error(0, error_type_null, vfile_error_to_error_id(asar_get_last_io_error()), filename);
638
639 return;
640 }
641
1/2
✓ Branch 0 taken 228 times.
✗ Branch 1 not taken.
228 file.contents =split(temp, "\n");
642
2/2
✓ Branch 0 taken 9476 times.
✓ Branch 1 taken 228 times.
9704 for (int i=0;file.contents[i];i++)
643 {
644 9476 file.numlines++;
645 4738 char * line= file.contents[i];
646 4738 char * comment=line;
647 9476 comment = strqchr(comment, ';');
648
2/2
✓ Branch 0 taken 2608 times.
✓ Branch 1 taken 9476 times.
12084 while (comment != nullptr)
649 {
650 2608 const char* comment_end = comment + strlen(comment);
651
2/2
✓ Branch 0 taken 2602 times.
✓ Branch 1 taken 6 times.
2608 if (comment_end - comment >= 2
652
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2602 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2602 && comment[1] == '[' && comment[2] == '['
653 && (comment_end[-1] != ']' || comment_end[-2] != ']'))
654 {
655 asar_throw_warning(0, warning_id_feature_deprecated, "comments starting with ;[[", "\";[[\" marks the start of a block comments in Asar 2.0 - either remove the \"[[\", or make sure the commented line ends on \"]]\"");
656 }
657
658
2/2
✓ Branch 0 taken 2604 times.
✓ Branch 1 taken 4 times.
2608 if (comment[1]!='@')
659 {
660 2604 comment[0]='\0';
661 }
662 else
663 {
664 4 comment[0] = ' ';
665 }
666 2608 comment = strqchr(comment, ';');
667 }
668
2/2
✓ Branch 0 taken 1408 times.
✓ Branch 1 taken 9476 times.
10884 while (strqchr(line, '\t')) *strqchr(line, '\t')=' ';
669
4/6
✓ Branch 0 taken 9476 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 9474 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
9476 if (!confirmquotes(line)) { thisline = i; thisblock = line; asar_throw_error(0, error_type_null, error_id_mismatched_quotes); line[0] = '\0'; }
670
1/2
✓ Branch 0 taken 9476 times.
✗ Branch 1 not taken.
9476 itrim(line, " ", " ", true); //todo make use strip
671 }
672
2/2
✓ Branch 0 taken 9476 times.
✓ Branch 1 taken 228 times.
9704 for(int i=0;file.contents[i];i++)
673 {
674 4738 char* line = file.contents[i];
675
7/8
✓ Branch 0 taken 1326 times.
✓ Branch 1 taken 8160 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 1316 times.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 4738 times.
9486 for (int j=1;strqrchr(line, ',') && !strqrchr(line, ',')[1] && file.contents[i+j];j++)
676 {
677 // not using strcat because the source and dest overlap here
678 5 char* otherline = file.contents[i+j];
679 10 char* line_end = line + strlen(line);
680
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 10 times.
138 while(*otherline) *line_end++ = *otherline++;
681 10 *line_end = '\0';
682 static char nullstr[]="";
683 10 file.contents[i+j]=nullstr;
684 }
685 }
686
1/2
✓ Branch 0 taken 228 times.
✗ Branch 1 not taken.
228 filecontents.create(absolutepath) = file;
687 } else { // filecontents.exists(absolutepath)
688
1/2
✓ Branch 0 taken 467 times.
✗ Branch 1 not taken.
934 file = filecontents.find(absolutepath);
689 }
690 581 bool in_macro_def=false;
691 1162 asarverallowed=true;
692
3/4
✓ Branch 0 taken 873488 times.
✓ Branch 1 taken 660 times.
✓ Branch 2 taken 873488 times.
✗ Branch 3 not taken.
874148 for (int i=0;file.contents[i] && i<file.numlines;i++)
693 {
694 try
695 {
696
1/2
✓ Branch 0 taken 436744 times.
✗ Branch 1 not taken.
436744 thisfilename= absolutepath;
697 873488 thisline=i;
698 873488 thisblock= nullptr;
699 873488 istoplevel=toplevel;
700
6/6
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 873332 times.
✓ Branch 2 taken 78 times.
✓ Branch 3 taken 78 times.
✓ Branch 4 taken 78 times.
✓ Branch 5 taken 436666 times.
873488 if (stribegin(file.contents[i], "macro ") && numif==numtrue)
701 {
702 // RPG Hacker: Commented out for Asar 1.81 backwards-compatibility.
703 // (From Asar 2.0 onwards, nested macro definitions will be well-defined).
704
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
156 if (in_macro_def /*|| inmacro*/) asar_throw_error(0, error_type_line, error_id_nested_macro_definition);
705 78 in_macro_def=true;
706
4/4
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 104 times.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 2 times.
156 if (!pass) startmacro(file.contents[i]+6);
707 }
708
5/6
✓ Branch 0 taken 436744 times.
✓ Branch 1 taken 436588 times.
✓ Branch 2 taken 156 times.
✓ Branch 3 taken 436588 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 78 times.
873332 else if (!stricmp(file.contents[i], "endmacro") && numif==numtrue)
709 {
710
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
156 if (!in_macro_def) asar_throw_error(0, error_type_line, error_id_misplaced_endmacro);
711 78 in_macro_def=false;
712
3/4
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 104 times.
✓ Branch 2 taken 52 times.
✗ Branch 3 not taken.
156 if (!pass) endmacro(true);
713 }
714
2/2
✓ Branch 0 taken 384 times.
✓ Branch 1 taken 872792 times.
873176 else if (in_macro_def)
715 {
716
3/4
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 192 times.
✓ Branch 2 taken 128 times.
✗ Branch 3 not taken.
384 if (!pass) tomacro(file.contents[i]);
717 }
718 else
719 {
720 872792 int prevnumif = numif;
721 436396 string connectedline;
722
1/2
✓ Branch 0 taken 436396 times.
✗ Branch 1 not taken.
872792 int skiplines = getconnectedlines<char**>(file.contents, i, connectedline);
723
2/2
✓ Branch 0 taken 872290 times.
✓ Branch 1 taken 502 times.
872792 assembleline(absolutepath, i, connectedline);
724
1/2
✓ Branch 0 taken 436145 times.
✗ Branch 1 not taken.
436145 thisfilename = absolutepath;
725 872290 i += skiplines;
726
17/18
✓ Branch 0 taken 449422 times.
✓ Branch 1 taken 422868 times.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 449362 times.
✓ Branch 4 taken 317452 times.
✓ Branch 5 taken 105476 times.
✓ Branch 6 taken 211756 times.
✓ Branch 7 taken 105696 times.
✓ Branch 8 taken 106204 times.
✓ Branch 9 taken 105480 times.
✓ Branch 10 taken 220 times.
✓ Branch 11 taken 105768 times.
✓ Branch 12 taken 105696 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 105480 times.
✓ Branch 15 taken 216 times.
✓ Branch 16 taken 105480 times.
✓ Branch 17 taken 330665 times.
1083754 if ((numif != prevnumif || single_line_for_tracker == 3) && (whilestatus[numif].iswhile || whilestatus[numif].is_for) && whilestatus[numif].cond)
727
1/2
✓ Branch 0 taken 105480 times.
✗ Branch 1 not taken.
210960 i = whilestatus[numif].startline - 1;
728 872792 }
729 }
730
2/2
✓ Branch 0 taken 502 times.
✓ Branch 1 taken 2 times.
504 catch (errline&) {}
731 }
732 660 thisline++;
733 660 thisblock= nullptr;
734
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 660 times.
660 if (in_macro_def)
735 {
736 asar_throw_error(0, error_type_null, error_id_unclosed_macro);
737 if (!pass) endmacro(false);
738 }
739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 660 times.
660 if (repeatnext!=1)
740 {
741 repeatnext=1;
742 asar_throw_error(0, error_type_null, error_id_rep_at_file_end);
743 }
744
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 660 times.
660 if (numif!=startif)
745 {
746 numif=startif;
747 numtrue=startif;
748 asar_throw_error(0, error_type_null, error_id_unclosed_if);
749 }
750 660 incsrcdepth--;
751
3/4
✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 330 times.
✓ Branch 3 taken 21 times.
1706 }
752
753 198 void parse_std_includes(const char* textfile, autoarray<string>& outarray)
754 {
755 198 char* content = readfilenative(textfile);
756
757
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 if (content != nullptr)
758 {
759 99 char* pos = content;
760
761
2/2
✓ Branch 0 taken 396 times.
✓ Branch 1 taken 198 times.
594 while (pos[0] != '\0')
762 {
763 198 string stdinclude;
764
765 do
766 {
767
3/4
✓ Branch 0 taken 9801 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9603 times.
✓ Branch 3 taken 198 times.
9801 if (pos[0] != '\r' && pos[0] != '\n')
768 {
769
1/2
✓ Branch 0 taken 5742 times.
✗ Branch 1 not taken.
9603 stdinclude += pos[0];
770 }
771 9801 pos++;
772
4/4
✓ Branch 0 taken 9603 times.
✓ Branch 1 taken 198 times.
✓ Branch 2 taken 9405 times.
✓ Branch 3 taken 198 times.
9801 } while (pos[0] != '\0' && pos[0] != '\n');
773
774
2/4
✓ Branch 0 taken 396 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 198 times.
✗ Branch 3 not taken.
396 stdinclude = strip_whitespace(stdinclude);
775
776
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 198 times.
396 if (stdinclude != "")
777 {
778
2/4
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 198 times.
198 if (!path_is_absolute(stdinclude))
779 {
780 stdinclude = dir(textfile) + stdinclude;
781 }
782
2/4
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 99 times.
✗ Branch 3 not taken.
198 outarray.append(normalize_path(stdinclude));
783 }
784 396 }
785
786 198 free(content);
787 }
788 198 }
789
790 198 void parse_std_defines(const char* textfile)
791 {
792
793 // RPG Hacker: add built-in defines.
794 // (They're not really standard defines, but I was lazy and this was
795 // one convenient place for doing it).
796 198 builtindefines.create("assembler") = "asar";
797
3/6
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 99 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 99 times.
✗ Branch 5 not taken.
198 builtindefines.create("assembler_ver") = dec(get_version_int());
798
799
2/2
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 99 times.
198 if(textfile == nullptr) return;
800
801 198 char* content = readfilenative(textfile);
802
803
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 if (content != nullptr)
804 {
805 99 char* pos = content;
806
2/2
✓ Branch 0 taken 1188 times.
✓ Branch 1 taken 198 times.
1386 while (*pos != 0) {
807 594 string define_name;
808 594 string define_val;
809
810
4/4
✓ Branch 0 taken 11880 times.
✓ Branch 1 taken 792 times.
✓ Branch 2 taken 11484 times.
✓ Branch 3 taken 396 times.
12672 while (*pos != '=' && *pos != '\n') {
811
1/2
✓ Branch 0 taken 5742 times.
✗ Branch 1 not taken.
11484 define_name += *pos;
812 11484 pos++;
813 }
814
4/4
✓ Branch 0 taken 990 times.
✓ Branch 1 taken 198 times.
✓ Branch 2 taken 396 times.
✓ Branch 3 taken 198 times.
1188 if (*pos != 0 && *pos != '\n') pos++; // skip =
815
3/4
✓ Branch 0 taken 5346 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4158 times.
✓ Branch 3 taken 1188 times.
5346 while (*pos != 0 && *pos != '\n') {
816
1/2
✓ Branch 0 taken 2079 times.
✗ Branch 1 not taken.
4158 define_val += *pos;
817 4158 pos++;
818 }
819
1/2
✓ Branch 0 taken 1188 times.
✗ Branch 1 not taken.
1188 if (*pos != 0)
820 1188 pos++; // skip \n
821 // clean define_name
822
2/4
✓ Branch 0 taken 1188 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 594 times.
✗ Branch 3 not taken.
1188 define_name = strip_whitespace(define_name);
823
2/4
✓ Branch 0 taken 1188 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 594 times.
✗ Branch 3 not taken.
1188 define_name = strip_prefix(define_name, '!', false); // remove leading ! if present
824
825
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 990 times.
1188 if (define_name == "")
826 {
827
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 if (define_val == "")
828 {
829 198 continue;
830 }
831
832 asar_throw_error(pass, error_type_null, error_id_stddefines_no_identifier);
833 }
834
835
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 990 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
990 if (!validatedefinename(define_name)) asar_throw_error(pass, error_type_null, error_id_cmdl_define_invalid, "stddefines.txt", define_name.data());
836
837 // clean define_val
838 495 const char* defval = define_val.data();
839 495 string cleaned_defval;
840
841
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 792 times.
990 if (*defval == 0) {
842 // no value
843
3/6
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 99 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
198 if (clidefines.exists(define_name)) asar_throw_error(pass, error_type_null, error_id_cmdl_define_override, "Std define", define_name.data());
844
2/4
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 99 times.
✗ Branch 3 not taken.
198 clidefines.create(define_name) = "";
845 198 continue;
846 }
847
848
3/4
✓ Branch 0 taken 396 times.
✓ Branch 1 taken 792 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 792 times.
1188 while (*defval == ' ' || *defval == '\t') defval++; // skip whitespace in beginning
849
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 594 times.
792 if (*defval == '"') {
850 198 defval++; // skip opening quote
851
3/4
✓ Branch 0 taken 2574 times.
✓ Branch 1 taken 198 times.
✓ Branch 2 taken 2574 times.
✗ Branch 3 not taken.
2772 while (*defval != '"' && *defval != 0)
852
1/2
✓ Branch 0 taken 1287 times.
✗ Branch 1 not taken.
2574 cleaned_defval += *defval++;
853
854
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 if (*defval == 0) {
855 asar_throw_error(pass, error_type_null, error_id_mismatched_quotes);
856 }
857 198 defval++; // skip closing quote
858
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 198 times.
198 while (*defval == ' ' || *defval == '\t') defval++; // skip whitespace
859
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
198 if (*defval != 0 && *defval != '\n')
860 asar_throw_error(pass, error_type_null, error_id_stddefine_after_closing_quote);
861
862
3/6
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 99 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
198 if (clidefines.exists(define_name)) asar_throw_error(pass, error_type_null, error_id_cmdl_define_override, "Std define", define_name.data());
863
2/4
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 99 times.
✗ Branch 3 not taken.
198 clidefines.create(define_name) = cleaned_defval;
864 198 continue;
865 }
866 else
867 {
868 // slightly hacky way to remove trailing whitespace
869 594 const char* defval_end = strchr(defval, '\n'); // slightly hacky way to get end of string or newline
870
1/2
✓ Branch 0 taken 594 times.
✗ Branch 1 not taken.
594 if (!defval_end) defval_end = strchr(defval, 0);
871 594 defval_end--;
872
3/4
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 594 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 594 times.
792 while (*defval_end == ' ' || *defval_end == '\t') defval_end--;
873
3/4
✓ Branch 0 taken 297 times.
✓ Branch 1 taken 297 times.
✓ Branch 2 taken 297 times.
✗ Branch 3 not taken.
594 cleaned_defval = string(defval, (int)(defval_end - defval + 1));
874
875
3/6
✓ Branch 0 taken 297 times.
✓ Branch 1 taken 297 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 297 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
594 if (clidefines.exists(define_name)) asar_throw_error(pass, error_type_null, error_id_cmdl_define_override, "Std define", define_name.data());
876
2/4
✓ Branch 0 taken 594 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 297 times.
✗ Branch 3 not taken.
594 clidefines.create(define_name) = cleaned_defval;
877 594 continue;
878 594 }
879
880 1188 }
881 198 free(content);
882 }
883 }
884
885 bool checksum_fix_enabled = true;
886 bool force_checksum_fix = false;
887
888 #define cfree(x) free((void*)x)
889 52 static void clearmacro(const string & key, macrodata* & macro)
890 {
891 (void)key;
892 52 macro->lines.~autoarray();
893 52 cfree(macro->fname);
894 52 cfree(macro->arguments[0]);
895 52 cfree(macro->arguments);
896 52 cfree(macro);
897 52 }
898
899 228 static void clearfile(const string & key, sourcefile& filecontent)
900 {
901 (void)key;
902 228 cfree(*filecontent.contents);
903 228 cfree(filecontent.contents);
904 228 }
905
906
1/2
✓ Branch 0 taken 990 times.
✗ Branch 1 not taken.
1980 static void adddefine(const string & key, string & value)
907 {
908
1/2
✓ Branch 0 taken 1980 times.
✗ Branch 1 not taken.
1980 if (!defines.exists(key)) defines.create(key) = value;
909 1980 }
910
911 static string symbolfile;
912
913 static void printsymbol_wla(const string& key, snes_label& label)
914 {
915 string line = hex2((label.pos & 0xFF0000)>>16)+":"+hex4(label.pos & 0xFFFF)+" "+key+"\n";
916 symbolfile += line;
917 }
918
919 static void printsymbol_nocash(const string& key, snes_label& label)
920 {
921 string line = hex8(label.pos & 0xFFFFFF)+" "+key+"\n";
922 symbolfile += line;
923 }
924
925 string create_symbols_file(string format, uint32_t romCrc){
926 format = lower(format);
927 symbolfile = "";
928 if(format == "wla")
929 {
930 symbolfile = "; wla symbolic information file\n";
931 symbolfile += "; generated by asar\n";
932
933 symbolfile += "\n[labels]\n";
934 labels.each(printsymbol_wla);
935
936 symbolfile += "\n[source files]\n";
937 const autoarray<AddressToLineMapping::FileInfo>& addrToLineFileList = addressToLineMapping.getFileList();
938 for (int i = 0; i < addrToLineFileList.count; ++i)
939 {
940 char addrToFileListStr[256];
941 snprintf(addrToFileListStr, 256, "%.4x %.8x %s\n",
942 i,
943 addrToLineFileList[i].fileCrc,
944 addrToLineFileList[i].filename.data()
945 );
946 symbolfile += addrToFileListStr;
947 }
948
949 symbolfile += "\n[rom checksum]\n";
950 {
951 char romCrcStr[32];
952 snprintf(romCrcStr, 32, "%.8x\n",
953 romCrc
954 );
955 symbolfile += romCrcStr;
956 }
957
958 symbolfile += "\n[addr-to-line mapping]\n";
959 const autoarray<AddressToLineMapping::AddrToLineInfo>& addrToLineInfo = addressToLineMapping.getAddrToLineInfo();
960 for (int i = 0; i < addrToLineInfo.count; ++i)
961 {
962 char addrToLineStr[32];
963 snprintf(addrToLineStr, 32, "%.2x:%.4x %.4x:%.8x\n",
964 (addrToLineInfo[i].addr & 0xFF0000) >> 16,
965 addrToLineInfo[i].addr & 0xFFFF,
966 addrToLineInfo[i].fileIdx & 0xFFFF,
967 addrToLineInfo[i].line & 0xFFFFFFFF
968 );
969 symbolfile += addrToLineStr;
970 }
971
972 }
973 else if (format == "nocash")
974 {
975 symbolfile = ";no$sns symbolic information file\n";
976 symbolfile += ";generated by asar\n";
977 symbolfile += "\n";
978 labels.each(printsymbol_nocash);
979 }
980 return symbolfile;
981 }
982
983 198 void reseteverything()
984 {
985 99 string str;
986 198 labels.reset();
987 198 defines.reset();
988
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 builtindefines.each(adddefine);
989
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 clidefines.each(adddefine);
990 198 structs.reset();
991
992
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 macros.each(clearmacro);
993 198 macros.reset();
994
995
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 filecontents.each(clearfile);
996 198 filecontents.reset();
997
998 198 writtenblocks.reset();
999
1000 198 optimizeforbank=-1;
1001 198 optimize_dp = optimize_dp_flag::NONE;
1002 198 dp_base = 0;
1003 198 optimize_address = optimize_address_flag::DEFAULT;
1004
1005
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 closecachedfiles();
1006
1007 198 incsrcdepth=0;
1008 198 errored = false;
1009 198 checksum_fix_enabled = true;
1010 198 force_checksum_fix = false;
1011
1012 198 default_math_pri = false;
1013 198 default_math_round_off = false;
1014 198 suppress_all_warnings = false;
1015
1016 #undef free
1017 297 }
1018