asar coverage - build #111


src/asar/
File: src/asar/main.cpp
Date: 2024-01-21 02:09:03
Lines:
450/552
81.5%
Functions:
19/22
86.4%
Branches:
523/903
57.9%

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 95 int get_version_int()
62 {
63 95 return asarver_maj * 10000 + asarver_min * 100 + asarver_bug;
64 }
65
66 46 bool setmapper()
67 {
68 23 int maxscore=-99999;
69 23 mapper_t bestmap=lorom;
70 46 mapper_t maps[]={lorom, hirom, exlorom, exhirom};
71
2/2
✓ Branch 0 taken 184 times.
✓ Branch 1 taken 46 times.
230 for (size_t mapid=0;mapid<sizeof(maps)/sizeof(maps[0]);mapid++)
72 {
73 184 mapper=maps[mapid];
74 92 int score=0;
75 92 int highbits=0;
76 92 bool foundnull=false;
77
2/2
✓ Branch 0 taken 3864 times.
✓ Branch 1 taken 184 times.
4048 for (int i=0;i<21;i++)
78 {
79 3864 unsigned char c=romdata[snestopc(0x00FFC0+i)];
80
3/4
✓ Branch 0 taken 1400 times.
✓ Branch 1 taken 2464 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1400 times.
3864 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 3864 times.
3864 if (c>=128) highbits++;
82
2/2
✓ Branch 0 taken 660 times.
✓ Branch 1 taken 3204 times.
3864 else if (is_upper(c)) score+=3;
83
2/2
✓ Branch 0 taken 264 times.
✓ Branch 1 taken 2940 times.
3204 else if (c==' ') score+=2;
84
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2940 times.
2940 else if (is_digit(c)) score+=1;
85
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2940 times.
2940 else if (is_lower(c)) score+=1;
86
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2940 times.
2940 else if (c=='-') score+=1;
87
2/2
✓ Branch 0 taken 1470 times.
✓ Branch 1 taken 1470 times.
2940 else if (!c) foundnull=true;
88 else score-=3;
89 }
90
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
184 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 46 times.
✓ Branch 1 taken 138 times.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 23 times.
207 if ((romdata[snestopc(0x00FFDE)]^romdata[snestopc(0x00FFDC)])!=0xFF ||
92
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
115 (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 46 times.
✓ Branch 1 taken 138 times.
184 if (score>maxscore)
95 {
96 23 maxscore=score;
97 23 bestmap=mapper;
98 }
99 }
100 46 mapper=bestmap;
101
102 //detect oddball mappers
103 46 int mapperbyte=romdata[snestopc(0x00FFD5)];
104 46 int romtypebyte=romdata[snestopc(0x00FFD6)];
105
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 if (mapper==lorom)
106 {
107
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 46 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.
46 if (mapperbyte==0x23 && (romtypebyte==0x32 || romtypebyte==0x34 || romtypebyte==0x35)) mapper=sa1rom;
108 }
109 46 return (maxscore>=0);
110 }
111
112 186 string getdecor()
113 {
114 93 string e;
115
2/4
✓ Branch 0 taken 186 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 93 times.
✗ Branch 3 not taken.
186 if (thisfilename)
116 {
117
2/4
✓ Branch 0 taken 93 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 93 times.
✗ Branch 3 not taken.
186 e+=STR thisfilename;
118
5/10
✓ Branch 0 taken 186 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 93 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 93 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 93 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 93 times.
✗ Branch 9 not taken.
279 if (thisline!=-1) e+=STR ":"+dec(thisline+1);
119
11/18
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 79 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 79 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.
200 if (callerfilename) e+=STR" (called from "+callerfilename+":"+dec(callerline+1)+")";
120
1/2
✓ Branch 0 taken 93 times.
✗ Branch 1 not taken.
186 e+=": ";
121 }
122 186 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 518 static int getlenforlabel(int insnespos, int thislabel, bool exists)
156 {
157
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 518 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
518 if (warnxkas && (((unsigned int)(thislabel^insnespos)&0xFFFF0000)==0))
158 asar_throw_warning(1, warning_id_xkas_label_access);
159 518 unsigned int bank = thislabel>>16;
160 518 unsigned int word = thislabel&0xFFFF;
161 518 unsigned int relaxed_bank = optimizeforbank < 0 ? 0 : optimizeforbank;
162
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 440 times.
518 if (!exists)
163 {
164
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 10 times.
78 if (!freespaced) freespaceextra++;
165 78 freespaced=true;
166 78 return 2;
167 }
168
6/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 428 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 3 times.
440 else if((optimize_dp == optimize_dp_flag::RAM) && bank == 0x7E && (word-dp_base < 0x100))
169 {
170 3 return 1;
171 }
172
6/8
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 416 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.
434 else if(optimize_dp == optimize_dp_flag::ALWAYS && (bank == 0x7E || !(bank & 0x40)) && (word-dp_base < 0x100))
173 {
174 6 return 1;
175 }
176
5/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 410 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
422 else if (optimize_address == optimize_address_flag::RAM && bank == 0x7E && word < 0x2000)
177 {
178 3 return 2;
179 }
180
6/10
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 410 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
416 else if (optimize_address == optimize_address_flag::MIRRORS && (bank == relaxed_bank || (!(bank & 0x40) && !(relaxed_bank & 0x40))) && word < 0x2000)
181 {
182 3 return 2;
183 }
184
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 410 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.
410 else if (optimize_address == optimize_address_flag::MIRRORS && !(bank & 0x40) && !(relaxed_bank & 0x40) && word < 0x8000)
185 {
186 return 2;
187 }
188
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 406 times.
410 else if (optimizeforbank>=0)
189 {
190
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if ((unsigned int)thislabel&0xFF000000) return 3;
191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 else if (bank==(unsigned int)optimizeforbank) return 2;
192 2 else return 3;
193 }
194
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 384 times.
406 else if ((unsigned int)(thislabel|insnespos)&0xFF000000)
195 {
196
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 if ((unsigned int)(thislabel^insnespos)&0xFF000000) return 3;
197 4 else return 2;
198 }
199
2/2
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 192 times.
384 else if ((thislabel^insnespos)&0xFF0000){ return 3; }
200 182 else { return 2;}
201 }
202
203
204 3156 bool is_hex_constant(const char* str){
205
2/2
✓ Branch 0 taken 2684 times.
✓ Branch 1 taken 472 times.
3156 if (*str=='$')
206 {
207 2684 str++;
208
2/2
✓ Branch 0 taken 9276 times.
✓ Branch 1 taken 2684 times.
11960 while(is_xdigit(*str)) {
209 9276 str++;
210 }
211
2/2
✓ Branch 0 taken 1342 times.
✓ Branch 1 taken 1342 times.
2684 if(*str=='\0'){
212 1342 return true;
213 }
214 }
215 236 return false;
216 }
217
218 2898 int getlen(const char * orgstr, bool optimizebankextraction)
219 {
220 2898 const char * str=orgstr;
221 2898 freespaced=false;
222
223 2898 const char* posneglabel = str;
224
1/2
✓ Branch 0 taken 1449 times.
✗ Branch 1 not taken.
2898 string posnegname = posneglabelname(&posneglabel, false);
225
226
4/4
✓ Branch 0 taken 2865 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 1416 times.
✓ Branch 3 taken 33 times.
2898 if (posnegname.length() > 0)
227 {
228
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 60 times.
66 if (*posneglabel != '\0') goto notposneglabel;
229
230
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 30 times.
80 if (!pass) return 2;
231 20 snes_label label_data;
232 // RPG Hacker: Umm... what kind of magic constant is this?
233 40 label_data.pos = 31415926;
234
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);
235
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 return getlenforlabel(snespos, (int)label_data.pos, found);
236 }
237 2835 notposneglabel:
238 1419 int len=0;
239
2/2
✓ Branch 0 taken 2984 times.
✓ Branch 1 taken 2838 times.
5822 while (*str)
240 {
241 1492 int thislen=0;
242 2984 bool maybebankextraction=(str==orgstr);
243
2/2
✓ Branch 0 taken 2276 times.
✓ Branch 1 taken 708 times.
2984 if (*str=='$')
244 {
245 2276 str++;
246 int i;
247
2/2
✓ Branch 0 taken 8796 times.
✓ Branch 1 taken 2276 times.
11072 for (i=0;is_xdigit(str[i]);i++);
248 //if (i&1) warn(S dec(i)+"-digit hex value");//blocked in getnum instead
249 2276 thislen=(i+1)/2;
250 2276 str+=i;
251 }
252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 708 times.
708 else if (*str=='%')
253 {
254 str++;
255 int i;
256 for (i=0;str[i]=='0' || str[i]=='1';i++);
257 //if (i&7) warn(S dec(i)+"-digit binary value");
258 thislen=(i+7)/8;
259 str+=i;
260 }
261
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 708 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
708 else if (str[0]=='\'' && str[2]=='\'')
262 {
263 thislen=1;
264 str+=3;
265 }
266
2/2
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 584 times.
708 else if (is_digit(*str))
267 {
268 124 int val=strtol(str, const_cast<char**>(&str), 10);
269
1/2
✓ Branch 0 taken 124 times.
✗ Branch 1 not taken.
124 if (val>=0) thislen=1;
270
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 62 times.
124 if (val>=256) thislen=2;
271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (val>=65536) thislen=3;
272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 if (val>=16777216) thislen=4;
273 }
274
7/10
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 478 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 239 times.
✓ Branch 9 taken 53 times.
584 else if (is_alpha(*str) || *str=='_' || *str=='.' || *str=='?')
275 {
276 239 snes_label thislabel;
277
1/2
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
478 bool exists=labelval(&str, &thislabel);
278
1/2
✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
478 thislen=getlenforlabel(snespos, (int)thislabel.pos, exists);
279 }
280 106 else str++;
281
4/4
✓ Branch 0 taken 398 times.
✓ Branch 1 taken 2586 times.
✓ Branch 2 taken 164 times.
✓ Branch 3 taken 70 times.
2984 if (optimizebankextraction && maybebankextraction &&
282
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")))
283 return 1;
284
2/2
✓ Branch 0 taken 1427 times.
✓ Branch 1 taken 65 times.
1492 if (thislen>len) len=thislen;
285 }
286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1419 times.
2838 if (len>3) return 3;
287 1419 return len;
288 2898 }
289
290 struct strcompare {
291 bool operator() (const char * lhs, const char * rhs) const
292 {
293 return strcmp(lhs, rhs)<0;
294 }
295 };
296
297 struct stricompare {
298 bool operator() (const char * lhs, const char * rhs) const
299 {
300 return stricmp(lhs, rhs)<0;
301 }
302 };
303
304 struct sourcefile {
305 char** contents;
306 int numlines;
307 };
308
309 static assocarr<sourcefile> filecontents;
310 assocarr<string> defines;
311 // needs to be separate because defines is reset between parsing arguments and patching
312 assocarr<string> clidefines;
313 assocarr<string> builtindefines;
314
315 1712 bool validatedefinename(const char * name)
316 {
317
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1712 times.
1712 if (!name[0]) return false;
318
2/2
✓ Branch 0 taken 17198 times.
✓ Branch 1 taken 1712 times.
18910 for (int i = 0;name[i];i++)
319 {
320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17198 times.
17198 if (!is_ualnum(name[i])) return false;
321 }
322
323 856 return true;
324 }
325
326 1506350 void resolvedefines(string& out, const char * start)
327 {
328
2/2
✓ Branch 0 taken 753174 times.
✓ Branch 1 taken 1 times.
753175 recurseblock rec;
329 753174 const char * here=start;
330
2/2
✓ Branch 0 taken 8614496 times.
✓ Branch 1 taken 1506336 times.
10120832 while (*here)
331 {
332
4/4
✓ Branch 0 taken 3126 times.
✓ Branch 1 taken 8611370 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 3114 times.
8614496 if (*here=='"' && emulatexkas)
333 {
334
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");
335
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
12 out+=*here++;
336
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++;
337
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
12 out+=*here++;
338 }
339
4/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 8614436 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 42 times.
8614484 else if (here[0] == '\\' && here[1] == '\\')
340 {
341 // allow using \\ as escape sequence
342
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 out += "\\";
343 6 here += 2;
344 }
345
4/4
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 8614436 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 12 times.
8614478 else if (here[0] == '\\' && here[1] == '!')
346 {
347 // allow using \! to escape !
348
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
30 out+="!";
349 30 here += 2;
350 }
351
2/2
✓ Branch 0 taken 635196 times.
✓ Branch 1 taken 7979252 times.
8614448 else if (*here=='!')
352 {
353
7/10
✓ Branch 0 taken 212784 times.
✓ Branch 1 taken 422412 times.
✓ Branch 2 taken 211224 times.
✓ Branch 3 taken 1560 times.
✓ Branch 4 taken 211026 times.
✓ Branch 5 taken 198 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 211026 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
354 317598 string defname;
355 635196 here++;
356
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 635088 times.
635196 if (*here=='{')
357 {
358 108 here++;
359 54 string unprocessedname;
360 54 int braces=1;
361 while (true)
362 {
363
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 1080 times.
1152 if (*here=='{') braces++;
364
2/2
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 972 times.
1152 if (*here=='}') braces--;
365
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);
366
2/2
✓ Branch 0 taken 576 times.
✓ Branch 1 taken 576 times.
1152 if (!braces) break;
367
1/2
✓ Branch 0 taken 522 times.
✗ Branch 1 not taken.
1044 unprocessedname+=*here++;
368 }
369
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
108 here++;
370
1/2
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
108 resolvedefines(defname, unprocessedname);
371
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);
372 108 }
373 else
374 {
375
4/4
✓ Branch 0 taken 654828 times.
✓ Branch 1 taken 317544 times.
✓ Branch 2 taken 327414 times.
✓ Branch 3 taken 317544 times.
1289916 while (is_ualnum(*here)) defname+=*here++;
376 }
377
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]==')')
378 asar_throw_warning(0, warning_id_xkas_eat_parentheses);
379 //if (emulatexkas && here[0]=='(' && here[1]==')') here+=2;
380
381
2/2
✓ Branch 0 taken 317598 times.
✓ Branch 1 taken 317598 times.
635196 if (first)
382 {
383 enum {
384 null,
385 append,
386 expand,
387 domath,
388 setifnotset,
389 } mode;
390 if(0);
391
2/2
✓ Branch 0 taken 270 times.
✓ Branch 1 taken 422142 times.
422412 else if (stribegin(here, " = ")) { here+=3; mode=null; }
392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 422142 times.
422142 else if (stribegin(here, " += ")) { here+=4; mode=append; }
393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 422142 times.
422142 else if (stribegin(here, " := ")) { here+=4; mode=expand; }
394
2/2
✓ Branch 0 taken 210966 times.
✓ Branch 1 taken 211176 times.
422142 else if (stribegin(here, " #= ")) { here+=4; mode=domath; }
395
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 211170 times.
211176 else if (stribegin(here, " ?= ")) { here+=4; mode=setifnotset; }
396 211170 else goto notdefineset;
397
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);
398 //else if (stribegin(here, " equ ")) here+=5;
399 105621 string val;
400
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 211200 times.
211242 if (*here=='"')
401 {
402 42 here++;
403 while (true)
404 {
405
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 147 times.
294 if (*here=='"')
406 {
407
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;
408
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 else if (here[1]=='"') here++;
409 else asar_throw_error(0, error_type_line, error_id_broken_define_declaration);
410 }
411
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
252 val+=*here++;
412 }
413 42 here++;
414 }
415 else
416 {
417
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++;
418 }
419 //if (strqchr(val.data(), ';')) *strqchr(val.data(), ';')=0;
420
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);
421
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);
422
423 // RPG Hacker: throw an error if we're trying to overwrite built-in defines.
424
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))
425 {
426
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());
427 }
428
429
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)
430 {
431 132 case null:
432 {
433
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;
434 132 break;
435 }
436 case append:
437 {
438 if (!defines.exists(defname)) asar_throw_error(0, error_type_line, error_id_define_not_found, defname.data());
439 string oldval = defines.find(defname);
440 val=oldval+val;
441 defines.create(defname) = val;
442 break;
443 }
444 case expand:
445 {
446 string newval;
447 resolvedefines(newval, val);
448 defines.create(defname) = newval;
449 break;
450 }
451 105483 case domath:
452 {
453 105483 string newval;
454
1/2
✓ Branch 0 taken 210966 times.
✗ Branch 1 not taken.
210966 resolvedefines(newval, val);
455
1/2
✓ Branch 0 taken 210966 times.
✗ Branch 1 not taken.
210966 double num= getnumdouble(newval);
456
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);
457
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);
458 105480 break;
459 210966 }
460 3 case setifnotset:
461 {
462
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;
463 3 break;
464 }
465 }
466 211242 }
467 else
468 {
469 318369 notdefineset:
470
5/6
✓ Branch 0 taken 211989 times.
✓ Branch 1 taken 211965 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 211965 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
423954 if (!defname) out+="!";
471 else
472 {
473
3/6
✓ Branch 0 taken 211965 times.
✓ Branch 1 taken 211965 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 211965 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
423930 if (!defines.exists(defname)) asar_throw_error(0, error_type_line, error_id_define_not_found, defname.data());
474 else {
475
2/4
✓ Branch 0 taken 211965 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 211965 times.
✗ Branch 3 not taken.
423930 string thisone = defines.find(defname);
476
1/2
✓ Branch 0 taken 423930 times.
✗ Branch 1 not taken.
423930 resolvedefines(out, thisone);
477 423930 }
478 }
479 }
480 635196 }
481
1/2
✓ Branch 0 taken 3989626 times.
✗ Branch 1 not taken.
7979252 else out+=*here++;
482 }
483 2259516 }
484
485 int repeatnext=1;
486
487 bool moreonline;
488 bool moreonlinecond;
489 int fakeendif;
490 bool asarverallowed;
491 bool istoplevel;
492
493 872546 void assembleline(const char * fname, int linenum, const char * line)
494 {
495
1/2
✓ Branch 0 taken 436273 times.
✗ Branch 1 not taken.
436273 recurseblock rec;
496 872546 bool moreonlinetmp=moreonline;
497 // randomdude999: redundant, assemblefile already converted the path to absolute
498 //string absolutepath = filesystem->create_absolute_path("", fname);
499
1/2
✓ Branch 0 taken 436273 times.
✗ Branch 1 not taken.
436273 string absolutepath = fname;
500
1/2
✓ Branch 0 taken 436273 times.
✗ Branch 1 not taken.
436273 thisfilename = absolutepath;
501 872546 thisline=linenum;
502 872546 thisblock= nullptr;
503 872546 single_line_for_tracker = 1;
504 try
505 {
506 436273 string tmp;
507
5/6
✓ Branch 0 taken 1032 times.
✓ Branch 1 taken 871514 times.
✓ Branch 2 taken 990 times.
✓ Branch 3 taken 42 times.
✓ Branch 4 taken 495 times.
✗ Branch 5 not taken.
872546 if(inmacro) tmp = replace_macro_args(line);
508
1/2
✓ Branch 0 taken 435757 times.
✗ Branch 1 not taken.
435757 else tmp = line;
509
4/8
✓ Branch 0 taken 872504 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 872504 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 872504 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 872504 times.
✗ Branch 7 not taken.
872504 clean(tmp);
510 436252 string out;
511
4/4
✓ Branch 0 taken 870998 times.
✓ Branch 1 taken 1506 times.
✓ Branch 2 taken 870984 times.
✓ Branch 3 taken 14 times.
872504 if (numif==numtrue) resolvedefines(out, tmp);
512
1/2
✓ Branch 0 taken 753 times.
✗ Branch 1 not taken.
753 else out=tmp;
513 // recheck quotes - defines can mess those up sometimes
514
4/6
✓ Branch 0 taken 872490 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 872484 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
872490 if (!confirmquotes(out)) asar_throw_error(0, error_type_line, error_id_mismatched_quotes);
515
1/2
✓ Branch 0 taken 872484 times.
✗ Branch 1 not taken.
872484 out.qreplace(": :", ": :", true);
516 //puts(out);
517
1/2
✓ Branch 0 taken 872484 times.
✗ Branch 1 not taken.
872484 autoptr<char**> blocks=qsplit(out.temp_raw(), " : ");
518 872484 moreonline=true;
519 872484 moreonlinecond=true;
520 872484 fakeendif=0;
521
2/2
✓ Branch 0 taken 874098 times.
✓ Branch 1 taken 871984 times.
1746082 for (int block=0;moreonline;block++)
522 {
523 874098 moreonline=(blocks[block+1] != nullptr);
524 874098 int repeatthis=repeatnext;
525 874098 repeatnext=1;
526
2/2
✓ Branch 0 taken 874098 times.
✓ Branch 1 taken 873598 times.
1747696 for (int i=0;i<repeatthis;i++)
527 {
528 try
529 {
530
1/2
✓ Branch 0 taken 437049 times.
✗ Branch 1 not taken.
874098 string stripped_block = blocks[block];
531
1/2
✓ Branch 0 taken 874098 times.
✗ Branch 1 not taken.
874098 strip_both(stripped_block, ' ', true);
532
533
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 437043 times.
874098 thisline=linenum;//do not optimize, this one is recursive
534 874098 thisblock = stripped_block.data();
535 437049 bool isspecialline = false;
536
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 874086 times.
874098 if (thisblock[0] == '@')
537 {
538
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");
539
540 6 isspecialline = true;
541 12 thisblock++;
542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 while (is_space(*thisblock))
543 {
544 thisblock++;
545 }
546 }
547
2/2
✓ Branch 0 taken 873440 times.
✓ Branch 1 taken 658 times.
874098 assembleblock(thisblock, isspecialline);
548
2/2
✓ Branch 0 taken 873438 times.
✓ Branch 1 taken 2 times.
873440 checkbankcross();
549 874098 }
550
2/2
✓ Branch 0 taken 500 times.
✓ Branch 1 taken 160 times.
660 catch (errblock&) {}
551
6/6
✓ Branch 0 taken 652518 times.
✓ Branch 1 taken 221080 times.
✓ Branch 2 taken 652506 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 326253 times.
✓ Branch 5 taken 110546 times.
873598 if (blocks[block][0]!='\0' && blocks[block][0]!='@') asarverallowed=false;
552 }
553
2/2
✓ Branch 0 taken 871576 times.
✓ Branch 1 taken 2022 times.
873598 if(single_line_for_tracker == 1) single_line_for_tracker = 0;
554 }
555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 871984 times.
871984 if(fakeendif)
556 {
557 thisline = linenum;
558 thisblock = blocks[0];
559 asar_throw_warning(0, warning_id_feature_deprecated, "inline if statements", "Add an \" : endif\" at the end of the line");
560 if (numif==numtrue) numtrue--;
561 numif--;
562 }
563 873566 }
564
2/2
✓ Branch 0 taken 502 times.
✓ Branch 1 taken 60 times.
562 catch (errline&) {}
565 872044 moreonline=moreonlinetmp;
566 1309070 }
567
568 int incsrcdepth=0;
569
570 // Returns true if a file is protected via
571 // an "includeonce".
572 1210 bool file_included_once(const char* file)
573 {
574
2/2
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 1168 times.
1408 for (int i = 0; i < includeonce.count; ++i)
575 {
576
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 120 times.
240 if (includeonce[i] == file)
577 {
578 21 return true;
579 }
580 }
581
582 584 return false;
583 }
584
585 1180 void assemblefile(const char * filename, bool toplevel)
586 {
587 1180 incsrcdepth++;
588
1/2
✓ Branch 0 taken 590 times.
✗ Branch 1 not taken.
1180 string absolutepath = filesystem->create_absolute_path(thisfilename, filename);
589
590
4/4
✓ Branch 0 taken 1159 times.
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 569 times.
1180 if (file_included_once(absolutepath))
591 {
592 21 return;
593 }
594
595
1/2
✓ Branch 0 taken 569 times.
✗ Branch 1 not taken.
569 string prevthisfilename = thisfilename;
596
1/2
✓ Branch 0 taken 569 times.
✗ Branch 1 not taken.
569 thisfilename = absolutepath;
597 1138 int prevline = thisline;
598 1138 thisline=-1;
599 1138 const char* prevthisblock = thisblock;
600 1138 thisblock= nullptr;
601 569 sourcefile file;
602 1138 file.contents = nullptr;
603 1138 file.numlines = 0;
604
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 459 times.
1138 int startif=numif;
605
4/4
✓ Branch 0 taken 679 times.
✓ Branch 1 taken 459 times.
✓ Branch 2 taken 110 times.
✓ Branch 3 taken 459 times.
1138 if (!filecontents.exists(absolutepath))
606 {
607
1/2
✓ Branch 0 taken 220 times.
✗ Branch 1 not taken.
220 char * temp= readfile(absolutepath, "");
608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 220 times.
220 if (!temp)
609 {
610 // RPG Hacker: This is so that we hopefully always end up with a proper decor
611 // and get better error messages.
612 thisfilename = prevthisfilename;
613 thisline = prevline;
614 thisblock = prevthisblock;
615
616 asar_throw_error(0, error_type_null, vfile_error_to_error_id(asar_get_last_io_error()), filename);
617
618 return;
619 }
620
1/2
✓ Branch 0 taken 220 times.
✗ Branch 1 not taken.
220 file.contents =split(temp, "\n");
621
2/2
✓ Branch 0 taken 9050 times.
✓ Branch 1 taken 220 times.
9270 for (int i=0;file.contents[i];i++)
622 {
623 9050 file.numlines++;
624 4525 char * line= file.contents[i];
625 4525 char * comment=line;
626 9050 comment = strqchr(comment, ';');
627
2/2
✓ Branch 0 taken 2478 times.
✓ Branch 1 taken 9050 times.
11528 while (comment != nullptr)
628 {
629 2478 const char* comment_end = comment + strlen(comment);
630
2/2
✓ Branch 0 taken 2472 times.
✓ Branch 1 taken 6 times.
2478 if (comment_end - comment >= 2
631
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2472 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2472 && comment[1] == '[' && comment[2] == '['
632 && (comment_end[-1] != ']' || comment_end[-2] != ']'))
633 {
634 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 \"]]\"");
635 }
636
637
2/2
✓ Branch 0 taken 2474 times.
✓ Branch 1 taken 4 times.
2478 if (comment[1]!='@')
638 {
639 2474 comment[0]='\0';
640 }
641 else
642 {
643 4 comment[0] = ' ';
644 }
645 2478 comment = strqchr(comment, ';');
646 }
647
2/2
✓ Branch 0 taken 1408 times.
✓ Branch 1 taken 9050 times.
10458 while (strqchr(line, '\t')) *strqchr(line, '\t')=' ';
648
4/6
✓ Branch 0 taken 9050 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 9048 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
9050 if (!confirmquotes(line)) { thisline = i; thisblock = line; asar_throw_error(0, error_type_null, error_id_mismatched_quotes); line[0] = '\0'; }
649
1/2
✓ Branch 0 taken 9050 times.
✗ Branch 1 not taken.
9050 itrim(line, " ", " ", true); //todo make use strip
650 }
651
2/2
✓ Branch 0 taken 9050 times.
✓ Branch 1 taken 220 times.
9270 for(int i=0;file.contents[i];i++)
652 {
653 4525 char* line = file.contents[i];
654
7/8
✓ Branch 0 taken 1324 times.
✓ Branch 1 taken 7736 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 1314 times.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 4525 times.
9060 for (int j=1;strqrchr(line, ',') && !strqrchr(line, ',')[1] && file.contents[i+j];j++)
655 {
656 // not using strcat because the source and dest overlap here
657 5 char* otherline = file.contents[i+j];
658 10 char* line_end = line + strlen(line);
659
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 10 times.
138 while(*otherline) *line_end++ = *otherline++;
660 10 *line_end = '\0';
661 static char nullstr[]="";
662 10 file.contents[i+j]=nullstr;
663 }
664 }
665
1/2
✓ Branch 0 taken 220 times.
✗ Branch 1 not taken.
220 filecontents.create(absolutepath) = file;
666 } else { // filecontents.exists(absolutepath)
667
1/2
✓ Branch 0 taken 459 times.
✗ Branch 1 not taken.
918 file = filecontents.find(absolutepath);
668 }
669 569 bool in_macro_def=false;
670 1138 asarverallowed=true;
671
3/4
✓ Branch 0 taken 872210 times.
✓ Branch 1 taken 636 times.
✓ Branch 2 taken 872210 times.
✗ Branch 3 not taken.
872846 for (int i=0;file.contents[i] && i<file.numlines;i++)
672 {
673 try
674 {
675
1/2
✓ Branch 0 taken 436105 times.
✗ Branch 1 not taken.
436105 thisfilename= absolutepath;
676 872210 thisline=i;
677 872210 thisblock= nullptr;
678 872210 istoplevel=toplevel;
679
6/6
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 872054 times.
✓ Branch 2 taken 78 times.
✓ Branch 3 taken 78 times.
✓ Branch 4 taken 78 times.
✓ Branch 5 taken 436027 times.
872210 if (stribegin(file.contents[i], "macro ") && numif==numtrue)
680 {
681
2/6
✓ Branch 0 taken 156 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 156 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
156 if (in_macro_def || inmacro) asar_throw_error(0, error_type_line, error_id_nested_macro_definition);
682 78 in_macro_def=true;
683
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);
684 }
685
5/6
✓ Branch 0 taken 436105 times.
✓ Branch 1 taken 435949 times.
✓ Branch 2 taken 156 times.
✓ Branch 3 taken 435949 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 78 times.
872054 else if (!stricmp(file.contents[i], "endmacro") && numif==numtrue)
686 {
687
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);
688 78 in_macro_def=false;
689
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);
690 }
691
2/2
✓ Branch 0 taken 384 times.
✓ Branch 1 taken 871514 times.
871898 else if (in_macro_def)
692 {
693
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]);
694 }
695 else
696 {
697 871514 int prevnumif = numif;
698 435757 string connectedline;
699
1/2
✓ Branch 0 taken 435757 times.
✗ Branch 1 not taken.
871514 int skiplines = getconnectedlines<char**>(file.contents, i, connectedline);
700
2/2
✓ Branch 0 taken 871012 times.
✓ Branch 1 taken 502 times.
871514 assembleline(absolutepath, i, connectedline);
701
1/2
✓ Branch 0 taken 435506 times.
✗ Branch 1 not taken.
435506 thisfilename = absolutepath;
702 871012 i += skiplines;
703
17/18
✓ Branch 0 taken 448168 times.
✓ Branch 1 taken 422844 times.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 448108 times.
✓ Branch 4 taken 317428 times.
✓ Branch 5 taken 105476 times.
✓ Branch 6 taken 211732 times.
✓ Branch 7 taken 105696 times.
✓ Branch 8 taken 106192 times.
✓ Branch 9 taken 105480 times.
✓ Branch 10 taken 220 times.
✓ Branch 11 taken 105756 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 330026 times.
1082464 if ((numif != prevnumif || single_line_for_tracker == 3) && (whilestatus[numif].iswhile || whilestatus[numif].is_for) && whilestatus[numif].cond)
704
1/2
✓ Branch 0 taken 105480 times.
✗ Branch 1 not taken.
210960 i = whilestatus[numif].startline - 1;
705 871514 }
706 }
707
2/2
✓ Branch 0 taken 502 times.
✓ Branch 1 taken 2 times.
504 catch (errline&) {}
708 }
709 636 thisline++;
710 636 thisblock= nullptr;
711
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 636 times.
636 if (in_macro_def)
712 {
713 asar_throw_error(0, error_type_null, error_id_unclosed_macro);
714 if (!pass) endmacro(false);
715 }
716
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 636 times.
636 if (repeatnext!=1)
717 {
718 repeatnext=1;
719 asar_throw_error(0, error_type_null, error_id_rep_at_file_end);
720 }
721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 636 times.
636 if (numif!=startif)
722 {
723 numif=startif;
724 numtrue=startif;
725 asar_throw_error(0, error_type_null, error_id_unclosed_if);
726 }
727 636 incsrcdepth--;
728
3/4
✓ Branch 0 taken 318 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 318 times.
✓ Branch 3 taken 21 times.
1682 }
729
730 190 void parse_std_includes(const char* textfile, autoarray<string>& outarray)
731 {
732 190 char* content = readfilenative(textfile);
733
734
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 if (content != nullptr)
735 {
736 95 char* pos = content;
737
738
2/2
✓ Branch 0 taken 380 times.
✓ Branch 1 taken 190 times.
570 while (pos[0] != '\0')
739 {
740 190 string stdinclude;
741
742 do
743 {
744
3/4
✓ Branch 0 taken 7410 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7220 times.
✓ Branch 3 taken 190 times.
7410 if (pos[0] != '\r' && pos[0] != '\n')
745 {
746
1/2
✓ Branch 0 taken 3515 times.
✗ Branch 1 not taken.
7220 stdinclude += pos[0];
747 }
748 7410 pos++;
749
4/4
✓ Branch 0 taken 7220 times.
✓ Branch 1 taken 190 times.
✓ Branch 2 taken 7030 times.
✓ Branch 3 taken 190 times.
7410 } while (pos[0] != '\0' && pos[0] != '\n');
750
751
2/4
✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 190 times.
✗ Branch 3 not taken.
380 stdinclude = strip_whitespace(stdinclude);
752
753
2/2
✓ Branch 0 taken 190 times.
✓ Branch 1 taken 190 times.
380 if (stdinclude != "")
754 {
755
2/4
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 190 times.
190 if (!path_is_absolute(stdinclude))
756 {
757 stdinclude = dir(textfile) + stdinclude;
758 }
759
2/4
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
190 outarray.append(normalize_path(stdinclude));
760 }
761 380 }
762
763 190 free(content);
764 }
765 190 }
766
767 190 void parse_std_defines(const char* textfile)
768 {
769
770 // RPG Hacker: add built-in defines.
771 // (They're not really standard defines, but I was lazy and this was
772 // one convenient place for doing it).
773 190 builtindefines.create("assembler") = "asar";
774
3/6
✓ 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.
190 builtindefines.create("assembler_ver") = dec(get_version_int());
775
776
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 95 times.
190 if(textfile == nullptr) return;
777
778 190 char* content = readfilenative(textfile);
779
780
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 if (content != nullptr)
781 {
782 95 char* pos = content;
783
2/2
✓ Branch 0 taken 1140 times.
✓ Branch 1 taken 190 times.
1330 while (*pos != 0) {
784 570 string define_name;
785 570 string define_val;
786
787
4/4
✓ Branch 0 taken 11400 times.
✓ Branch 1 taken 760 times.
✓ Branch 2 taken 11020 times.
✓ Branch 3 taken 380 times.
12160 while (*pos != '=' && *pos != '\n') {
788
1/2
✓ Branch 0 taken 5510 times.
✗ Branch 1 not taken.
11020 define_name += *pos;
789 11020 pos++;
790 }
791
4/4
✓ Branch 0 taken 950 times.
✓ Branch 1 taken 190 times.
✓ Branch 2 taken 380 times.
✓ Branch 3 taken 190 times.
1140 if (*pos != 0 && *pos != '\n') pos++; // skip =
792
3/4
✓ Branch 0 taken 5130 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3990 times.
✓ Branch 3 taken 1140 times.
5130 while (*pos != 0 && *pos != '\n') {
793
1/2
✓ Branch 0 taken 1995 times.
✗ Branch 1 not taken.
3990 define_val += *pos;
794 3990 pos++;
795 }
796
1/2
✓ Branch 0 taken 1140 times.
✗ Branch 1 not taken.
1140 if (*pos != 0)
797 1140 pos++; // skip \n
798 // clean define_name
799
2/4
✓ Branch 0 taken 1140 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 570 times.
✗ Branch 3 not taken.
1140 define_name = strip_whitespace(define_name);
800
2/4
✓ Branch 0 taken 1140 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 570 times.
✗ Branch 3 not taken.
1140 define_name = strip_prefix(define_name, '!', false); // remove leading ! if present
801
802
2/2
✓ Branch 0 taken 190 times.
✓ Branch 1 taken 950 times.
1140 if (define_name == "")
803 {
804
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 if (define_val == "")
805 {
806 190 continue;
807 }
808
809 asar_throw_error(pass, error_type_null, error_id_stddefines_no_identifier);
810 }
811
812
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 950 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
950 if (!validatedefinename(define_name)) asar_throw_error(pass, error_type_null, error_id_cmdl_define_invalid, "stddefines.txt", define_name.data());
813
814 // clean define_val
815 475 const char* defval = define_val.data();
816 475 string cleaned_defval;
817
818
2/2
✓ Branch 0 taken 190 times.
✓ Branch 1 taken 760 times.
950 if (*defval == 0) {
819 // no value
820
3/6
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 95 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
190 if (clidefines.exists(define_name)) asar_throw_error(pass, error_type_null, error_id_cmdl_define_override, "Std define", define_name.data());
821
2/4
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
190 clidefines.create(define_name) = "";
822 190 continue;
823 }
824
825
3/4
✓ Branch 0 taken 380 times.
✓ Branch 1 taken 760 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 760 times.
1140 while (*defval == ' ' || *defval == '\t') defval++; // skip whitespace in beginning
826
2/2
✓ Branch 0 taken 190 times.
✓ Branch 1 taken 570 times.
760 if (*defval == '"') {
827 190 defval++; // skip opening quote
828
3/4
✓ Branch 0 taken 2470 times.
✓ Branch 1 taken 190 times.
✓ Branch 2 taken 2470 times.
✗ Branch 3 not taken.
2660 while (*defval != '"' && *defval != 0)
829
1/2
✓ Branch 0 taken 1235 times.
✗ Branch 1 not taken.
2470 cleaned_defval += *defval++;
830
831
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
190 if (*defval == 0) {
832 asar_throw_error(pass, error_type_null, error_id_mismatched_quotes);
833 }
834 190 defval++; // skip closing quote
835
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 190 times.
190 while (*defval == ' ' || *defval == '\t') defval++; // skip whitespace
836
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
190 if (*defval != 0 && *defval != '\n')
837 asar_throw_error(pass, error_type_null, error_id_stddefine_after_closing_quote);
838
839
3/6
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 95 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
190 if (clidefines.exists(define_name)) asar_throw_error(pass, error_type_null, error_id_cmdl_define_override, "Std define", define_name.data());
840
2/4
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
190 clidefines.create(define_name) = cleaned_defval;
841 190 continue;
842 }
843 else
844 {
845 // slightly hacky way to remove trailing whitespace
846 570 const char* defval_end = strchr(defval, '\n'); // slightly hacky way to get end of string or newline
847
1/2
✓ Branch 0 taken 570 times.
✗ Branch 1 not taken.
570 if (!defval_end) defval_end = strchr(defval, 0);
848 570 defval_end--;
849
3/4
✓ Branch 0 taken 190 times.
✓ Branch 1 taken 570 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 570 times.
760 while (*defval_end == ' ' || *defval_end == '\t') defval_end--;
850
3/4
✓ Branch 0 taken 285 times.
✓ Branch 1 taken 285 times.
✓ Branch 2 taken 285 times.
✗ Branch 3 not taken.
570 cleaned_defval = string(defval, (int)(defval_end - defval + 1));
851
852
3/6
✓ Branch 0 taken 285 times.
✓ Branch 1 taken 285 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 285 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
570 if (clidefines.exists(define_name)) asar_throw_error(pass, error_type_null, error_id_cmdl_define_override, "Std define", define_name.data());
853
2/4
✓ Branch 0 taken 570 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 285 times.
✗ Branch 3 not taken.
570 clidefines.create(define_name) = cleaned_defval;
854 570 continue;
855 570 }
856
857 1140 }
858 190 free(content);
859 }
860 }
861
862 bool checksum_fix_enabled = true;
863 bool force_checksum_fix = false;
864
865 #define cfree(x) free((void*)x)
866 52 static void clearmacro(const string & key, macrodata* & macro)
867 {
868 (void)key;
869 52 macro->lines.~autoarray();
870 52 cfree(macro->fname);
871 52 cfree(macro->arguments[0]);
872 52 cfree(macro->arguments);
873 52 cfree(macro);
874 52 }
875
876 220 static void clearfile(const string & key, sourcefile& filecontent)
877 {
878 (void)key;
879 220 cfree(*filecontent.contents);
880 220 cfree(filecontent.contents);
881 220 }
882
883
1/2
✓ Branch 0 taken 950 times.
✗ Branch 1 not taken.
1900 static void adddefine(const string & key, string & value)
884 {
885
1/2
✓ Branch 0 taken 1900 times.
✗ Branch 1 not taken.
1900 if (!defines.exists(key)) defines.create(key) = value;
886 1900 }
887
888 static string symbolfile;
889
890 static void printsymbol_wla(const string& key, snes_label& label)
891 {
892 string line = hex2((label.pos & 0xFF0000)>>16)+":"+hex4(label.pos & 0xFFFF)+" "+key+"\n";
893 symbolfile += line;
894 }
895
896 static void printsymbol_nocash(const string& key, snes_label& label)
897 {
898 string line = hex8(label.pos & 0xFFFFFF)+" "+key+"\n";
899 symbolfile += line;
900 }
901
902 string create_symbols_file(string format, uint32_t romCrc){
903 format = lower(format);
904 symbolfile = "";
905 if(format == "wla")
906 {
907 symbolfile = "; wla symbolic information file\n";
908 symbolfile += "; generated by asar\n";
909
910 symbolfile += "\n[labels]\n";
911 labels.each(printsymbol_wla);
912
913 symbolfile += "\n[source files]\n";
914 const autoarray<AddressToLineMapping::FileInfo>& addrToLineFileList = addressToLineMapping.getFileList();
915 for (int i = 0; i < addrToLineFileList.count; ++i)
916 {
917 char addrToFileListStr[256];
918 snprintf(addrToFileListStr, 256, "%.4x %.8x %s\n",
919 i,
920 addrToLineFileList[i].fileCrc,
921 addrToLineFileList[i].filename.data()
922 );
923 symbolfile += addrToFileListStr;
924 }
925
926 symbolfile += "\n[rom checksum]\n";
927 {
928 char romCrcStr[32];
929 snprintf(romCrcStr, 32, "%.8x\n",
930 romCrc
931 );
932 symbolfile += romCrcStr;
933 }
934
935 symbolfile += "\n[addr-to-line mapping]\n";
936 const autoarray<AddressToLineMapping::AddrToLineInfo>& addrToLineInfo = addressToLineMapping.getAddrToLineInfo();
937 for (int i = 0; i < addrToLineInfo.count; ++i)
938 {
939 char addrToLineStr[32];
940 snprintf(addrToLineStr, 32, "%.2x:%.4x %.4x:%.8x\n",
941 (addrToLineInfo[i].addr & 0xFF0000) >> 16,
942 addrToLineInfo[i].addr & 0xFFFF,
943 addrToLineInfo[i].fileIdx & 0xFFFF,
944 addrToLineInfo[i].line & 0xFFFFFFFF
945 );
946 symbolfile += addrToLineStr;
947 }
948
949 }
950 else if (format == "nocash")
951 {
952 symbolfile = ";no$sns symbolic information file\n";
953 symbolfile += ";generated by asar\n";
954 symbolfile += "\n";
955 labels.each(printsymbol_nocash);
956 }
957 return symbolfile;
958 }
959
960 190 void reseteverything()
961 {
962 95 string str;
963 190 labels.reset();
964 190 defines.reset();
965
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 builtindefines.each(adddefine);
966
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 clidefines.each(adddefine);
967 190 structs.reset();
968
969
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 macros.each(clearmacro);
970 190 macros.reset();
971
972
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 filecontents.each(clearfile);
973 190 filecontents.reset();
974
975 190 writtenblocks.reset();
976
977 190 optimizeforbank=-1;
978 190 optimize_dp = optimize_dp_flag::NONE;
979 190 dp_base = 0;
980 190 optimize_address = optimize_address_flag::DEFAULT;
981
982
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 closecachedfiles();
983
984 190 incsrcdepth=0;
985 190 errored = false;
986 190 checksum_fix_enabled = true;
987 190 force_checksum_fix = false;
988
989 190 default_math_pri = false;
990 190 default_math_round_off = false;
991 190 suppress_all_warnings = false;
992
993 #undef free
994 285 }
995