asar coverage - build #87


src/asar/
File: src/asar/main.cpp
Date: 2024-01-19 13:47:25
Lines:
392/471
83.2%
Functions:
18/22
81.8%
Branches:
390/637
61.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 int get_version_int()
62 {
63 return asarver_maj * 10000 + asarver_min * 100 + asarver_bug;
64 }
65
66 46 bool setmapper()
67 {
68 int maxscore=-99999;
69 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 int score=0;
75 int highbits=0;
76 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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3864 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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2940 times.
2940 else if (!c) foundnull=true;
88 else score-=3;
89 }
90
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
184 if (highbits>0 && highbits<=14) score-=21;//high bits set on some, but not all, bytes = unlikely to be a ROM
91
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 138 times.
184 if ((romdata[snestopc(0x00FFDE)]^romdata[snestopc(0x00FFDC)])!=0xFF ||
92
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 (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 maxscore=score;
97 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/6
✗ 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.
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
1/2
✓ Branch 0 taken 186 times.
✗ Branch 1 not taken.
186 if (thisfilename)
116 {
117 186 e+=STR thisfilename;
118
1/2
✓ Branch 0 taken 186 times.
✗ Branch 1 not taken.
372 if (thisline!=-1) e+=STR ":"+dec(thisline+1);
119
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 158 times.
214 if (callerfilename) e+=STR" (called from "+callerfilename+":"+dec(callerline+1)+")";
120 186 e+=": ";
121 }
122 186 return e;
123 }
124
125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 asar_error_id vfile_error_to_error_id(virtual_file_error vfile_error)
126 {
127 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 case vfe_not_regular_file:
134 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
5/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 428 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
440 else if((optimize_dp == optimize_dp_flag::RAM) && bank == 0x7E && (word-dp_base < 0x100))
169 {
170 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 6 times.
✓ Branch 7 taken 12 times.
434 else if(optimize_dp == optimize_dp_flag::ALWAYS && (bank == 0x7E || !(bank & 0x40)) && (word-dp_base < 0x100))
173 {
174 return 1;
175 }
176
4/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 410 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
422 else if (optimize_address == optimize_address_flag::RAM && bank == 0x7E && word < 0x2000)
177 {
178 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 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
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
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 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 8 times.
✓ Branch 1 taken 14 times.
22 if ((unsigned int)(thislabel^insnespos)&0xFF000000) return 3;
197 else return 2;
198 }
199
2/2
✓ Branch 0 taken 364 times.
✓ Branch 1 taken 20 times.
384 else if ((thislabel^insnespos)&0xFF0000){ return 3; }
200 else { return 2;}
201 }
202
203
204 3144 bool is_hex_constant(const char* str){
205
2/2
✓ Branch 0 taken 2672 times.
✓ Branch 1 taken 472 times.
3144 if (*str=='$')
206 {
207 2672 str++;
208
2/2
✓ Branch 0 taken 9252 times.
✓ Branch 1 taken 2672 times.
11924 while(is_xdigit(*str)) {
209 9252 str++;
210 }
211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2672 times.
2672 if(*str=='\0'){
212 return true;
213 }
214 }
215 return false;
216 }
217
218 2886 int getlen(const char * orgstr, bool optimizebankextraction)
219 {
220 2886 const char * str=orgstr;
221 2886 freespaced=false;
222
223 2886 const char* posneglabel = str;
224 2886 string posnegname = posneglabelname(&posneglabel, false);
225
226
2/2
✓ Branch 0 taken 2820 times.
✓ Branch 1 taken 66 times.
2886 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 40 times.
✓ Branch 1 taken 20 times.
100 if (!pass) return 2;
231 snes_label label_data;
232 // RPG Hacker: Umm... what kind of magic constant is this?
233 40 label_data.pos = 31415926;
234
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 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 2820 notposneglabel:
238 int len=0;
239
2/2
✓ Branch 0 taken 2972 times.
✓ Branch 1 taken 2826 times.
5798 while (*str)
240 {
241 int thislen=0;
242 2972 bool maybebankextraction=(str==orgstr);
243
2/2
✓ Branch 0 taken 2264 times.
✓ Branch 1 taken 708 times.
2972 if (*str=='$')
244 {
245 2264 str++;
246 int i;
247
2/2
✓ Branch 0 taken 8772 times.
✓ Branch 1 taken 2264 times.
11036 for (i=0;is_xdigit(str[i]);i++);
248 //if (i&1) warn(S dec(i)+"-digit hex value");//blocked in getnum instead
249 2264 thislen=(i+1)/2;
250 2264 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 106 times.
✓ Branch 1 taken 18 times.
124 if (val>=256) thislen=2;
271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (val>=65536) thislen=3;
272 if (val>=16777216) thislen=4;
273 }
274
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 478 times.
584 else if (is_alpha(*str) || *str=='_' || *str=='.' || *str=='?')
275 {
276 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
2/2
✓ Branch 0 taken 316 times.
✓ Branch 1 taken 2656 times.
2972 if (optimizebankextraction && maybebankextraction &&
282
3/6
✓ Branch 0 taken 316 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 316 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 316 times.
✗ Branch 5 not taken.
316 (!strcmp(str, ">>16") || !strcmp(str, "/65536") || !strcmp(str, "/$10000")))
283 return 1;
284 if (thislen>len) len=thislen;
285 }
286 2826 if (len>3) return 3;
287 return len;
288 2886 }
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 return true;
324 }
325
326 1506236 void resolvedefines(string& out, const char * start)
327 {
328 753118 recurseblock rec;
329 const char * here=start;
330
2/2
✓ Branch 0 taken 8613686 times.
✓ Branch 1 taken 1506222 times.
10119908 while (*here)
331 {
332
4/4
✓ Branch 0 taken 3126 times.
✓ Branch 1 taken 8610560 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 3114 times.
8613686 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 12 out+=*here++;
336
3/4
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 12 times.
48 while (*here && *here!='"') out+=*here++;
337 12 out+=*here++;
338 }
339
4/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 8613626 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 42 times.
8613674 else if (here[0] == '\\' && here[1] == '\\')
340 {
341 // allow using \\ as escape sequence
342 6 out += "\\";
343 6 here += 2;
344 }
345
4/4
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 8613626 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 12 times.
8613668 else if (here[0] == '\\' && here[1] == '!')
346 {
347 // allow using \! to escape !
348 30 out+="!";
349 30 here += 2;
350 }
351
2/2
✓ Branch 0 taken 635196 times.
✓ Branch 1 taken 7978442 times.
8613638 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 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 1044 times.
✓ Branch 1 taken 108 times.
1152 if (!braces) break;
367 1044 unprocessedname+=*here++;
368 }
369
1/2
✓ Branch 0 taken 108 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
2/2
✓ Branch 0 taken 654828 times.
✓ Branch 1 taken 635088 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 422412 times.
✓ Branch 1 taken 212784 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 246 times.
✓ Branch 1 taken 48 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 252 val+=*here++;
412 }
413 42 here++;
414 }
415 else
416 {
417
3/4
✓ Branch 0 taken 848736 times.
✓ Branch 1 taken 211200 times.
✓ Branch 2 taken 848736 times.
✗ Branch 3 not taken.
1059936 while (*here && *here!=' ') val+=*here++;
418 }
419 //if (strqchr(val.data(), ';')) *strqchr(val.data(), ';')=0;
420
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 (*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
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 211236 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/5
✓ Branch 0 taken 264 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 210966 times.
✓ Branch 4 taken 6 times.
211236 switch (mode)
430 {
431 case null:
432 {
433
1/2
✓ Branch 0 taken 264 times.
✗ Branch 1 not taken.
264 defines.create(defname) = val;
434 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
1/2
✓ Branch 0 taken 210960 times.
✗ Branch 1 not taken.
210960 defines.create(defname) = ftostr(num);
458 break;
459 210966 }
460 case setifnotset:
461 {
462
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 if (!defines.exists(defname)) defines.create(defname) = val;
463 break;
464 }
465 }
466 211242 }
467 else
468 {
469 212784 notdefineset:
470
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 423930 times.
423954 if (!defname) out+="!";
471 else
472 {
473
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 423930 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
423930 if (!defines.exists(defname)) asar_throw_error(0, error_type_line, error_id_define_not_found, defname.data());
474 else {
475 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 7978442 else out+=*here++;
482 }
483 1506234 }
484
485 int repeatnext=1;
486
487 bool moreonline;
488 bool moreonlinecond;
489 int fakeendif;
490 bool asarverallowed;
491 bool istoplevel;
492
493 872432 void assembleline(const char * fname, int linenum, const char * line)
494 {
495 436216 recurseblock rec;
496 872432 bool moreonlinetmp=moreonline;
497 // randomdude999: redundant, assemblefile already converted the path to absolute
498 //string absolutepath = filesystem->create_absolute_path("", fname);
499 436216 string absolutepath = fname;
500 thisfilename = absolutepath;
501 872432 thisline=linenum;
502 872432 thisblock= nullptr;
503 872432 single_line_for_tracker = 1;
504 try
505 {
506 436216 string tmp;
507
4/4
✓ Branch 0 taken 1032 times.
✓ Branch 1 taken 871400 times.
✓ Branch 2 taken 990 times.
✓ Branch 3 taken 42 times.
872432 if(inmacro) tmp = replace_macro_args(line);
508 else tmp = line;
509
4/8
✓ Branch 0 taken 872390 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 872390 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 872390 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 872390 times.
✗ Branch 7 not taken.
872390 clean(tmp);
510 436195 string out;
511
4/4
✓ Branch 0 taken 870884 times.
✓ Branch 1 taken 1506 times.
✓ Branch 2 taken 870870 times.
✓ Branch 3 taken 14 times.
872390 if (numif==numtrue) resolvedefines(out, tmp);
512 else out=tmp;
513 // recheck quotes - defines can mess those up sometimes
514
4/6
✓ Branch 0 taken 872376 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 872370 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
872376 if (!confirmquotes(out)) asar_throw_error(0, error_type_line, error_id_mismatched_quotes);
515
1/2
✓ Branch 0 taken 872370 times.
✗ Branch 1 not taken.
872370 out.qreplace(": :", ": :", true);
516 //puts(out);
517
1/2
✓ Branch 0 taken 872370 times.
✗ Branch 1 not taken.
872370 autoptr<char**> blocks=qsplit(out.temp_raw(), " : ");
518 872370 moreonline=true;
519 872370 moreonlinecond=true;
520 872370 fakeendif=0;
521
2/2
✓ Branch 0 taken 873984 times.
✓ Branch 1 taken 871870 times.
1745854 for (int block=0;moreonline;block++)
522 {
523 873984 moreonline=(blocks[block+1] != nullptr);
524 873984 int repeatthis=repeatnext;
525 873984 repeatnext=1;
526
2/2
✓ Branch 0 taken 873984 times.
✓ Branch 1 taken 873484 times.
1747468 for (int i=0;i<repeatthis;i++)
527 {
528 try
529 {
530 873984 string stripped_block = blocks[block];
531
1/2
✓ Branch 0 taken 873984 times.
✗ Branch 1 not taken.
873984 strip_both(stripped_block, ' ', true);
532
533
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 873972 times.
873984 thisline=linenum;//do not optimize, this one is recursive
534 873984 thisblock = stripped_block.data();
535 bool isspecialline = false;
536
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 873972 times.
873984 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 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 873326 times.
✓ Branch 1 taken 658 times.
873984 assembleblock(thisblock, isspecialline);
548
2/2
✓ Branch 0 taken 873324 times.
✓ Branch 1 taken 2 times.
873326 checkbankcross();
549 873984 }
550
2/2
✓ Branch 0 taken 500 times.
✓ Branch 1 taken 160 times.
660 catch (errblock&) {}
551
4/4
✓ Branch 0 taken 652470 times.
✓ Branch 1 taken 221014 times.
✓ Branch 2 taken 652458 times.
✓ Branch 3 taken 12 times.
873484 if (blocks[block][0]!='\0' && blocks[block][0]!='@') asarverallowed=false;
552 }
553
2/2
✓ Branch 0 taken 871462 times.
✓ Branch 1 taken 2022 times.
873484 if(single_line_for_tracker == 1) single_line_for_tracker = 0;
554 }
555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 871870 times.
871870 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 873452 }
564
2/2
✓ Branch 0 taken 502 times.
✓ Branch 1 taken 60 times.
562 catch (errline&) {}
565 871930 moreonline=moreonlinetmp;
566 872934 }
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 198 times.
✓ Branch 1 taken 42 times.
240 if (includeonce[i] == file)
577 {
578 return true;
579 }
580 }
581
582 return false;
583 }
584
585 1180 void assemblefile(const char * filename, bool toplevel)
586 {
587 1180 incsrcdepth++;
588 1180 string absolutepath = filesystem->create_absolute_path(thisfilename, filename);
589
590
2/2
✓ Branch 0 taken 1138 times.
✓ Branch 1 taken 42 times.
1180 if (file_included_once(absolutepath))
591 {
592 return;
593 }
594
595 569 string prevthisfilename = thisfilename;
596 thisfilename = absolutepath;
597 1138 int prevline = thisline;
598 1138 thisline=-1;
599 1138 const char* prevthisblock = thisblock;
600 1138 thisblock= nullptr;
601 sourcefile file;
602 1138 file.contents = nullptr;
603 1138 file.numlines = 0;
604
2/2
✓ Branch 0 taken 220 times.
✓ Branch 1 taken 918 times.
1138 int startif=numif;
605
2/2
✓ Branch 0 taken 220 times.
✓ Branch 1 taken 918 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 9012 times.
✓ Branch 1 taken 220 times.
9232 for (int i=0;file.contents[i];i++)
622 {
623 9012 file.numlines++;
624 char * line= file.contents[i];
625 char * comment=line;
626 9012 comment = strqchr(comment, ';');
627
2/2
✓ Branch 0 taken 2468 times.
✓ Branch 1 taken 9012 times.
11480 while (comment != nullptr)
628 {
629 2468 const char* comment_end = comment + strlen(comment);
630
2/2
✓ Branch 0 taken 2462 times.
✓ Branch 1 taken 6 times.
2468 if (comment_end - comment >= 2
631
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2462 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2462 && 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 2464 times.
✓ Branch 1 taken 4 times.
2468 if (comment[1]!='@')
638 {
639 2464 comment[0]='\0';
640 }
641 else
642 {
643 4 comment[0] = ' ';
644 }
645 2468 comment = strqchr(comment, ';');
646 }
647
2/2
✓ Branch 0 taken 1398 times.
✓ Branch 1 taken 9012 times.
10410 while (strqchr(line, '\t')) *strqchr(line, '\t')=' ';
648
4/6
✓ Branch 0 taken 9012 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 9010 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
9012 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 9012 times.
✗ Branch 1 not taken.
9012 itrim(line, " ", " ", true); //todo make use strip
650 }
651
2/2
✓ Branch 0 taken 9012 times.
✓ Branch 1 taken 220 times.
9232 for(int i=0;file.contents[i];i++)
652 {
653 char* line = file.contents[i];
654
5/6
✓ Branch 0 taken 1322 times.
✓ Branch 1 taken 7700 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 1312 times.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
9022 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 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 918 file = filecontents.find(absolutepath);
668 }
669 bool in_macro_def=false;
670 1138 asarverallowed=true;
671
3/4
✓ Branch 0 taken 872096 times.
✓ Branch 1 taken 636 times.
✓ Branch 2 taken 872096 times.
✗ Branch 3 not taken.
872732 for (int i=0;file.contents[i] && i<file.numlines;i++)
672 {
673 try
674 {
675 thisfilename= absolutepath;
676 872096 thisline=i;
677 872096 thisblock= nullptr;
678 872096 istoplevel=toplevel;
679
3/4
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 871940 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 156 times.
872096 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 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 436048 times.
✓ Branch 1 taken 435892 times.
✓ Branch 2 taken 156 times.
✓ Branch 3 taken 435892 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 78 times.
871940 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 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 871400 times.
871784 else if (in_macro_def)
692 {
693
3/4
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 128 times.
✓ Branch 2 taken 128 times.
✗ Branch 3 not taken.
384 if (!pass) tomacro(file.contents[i]);
694 }
695 else
696 {
697 871400 int prevnumif = numif;
698 435700 string connectedline;
699 871400 int skiplines = getconnectedlines<char**>(file.contents, i, connectedline);
700
2/2
✓ Branch 0 taken 870898 times.
✓ Branch 1 taken 502 times.
871400 assembleline(absolutepath, i, connectedline);
701 thisfilename = absolutepath;
702 870898 i += skiplines;
703
10/10
✓ Branch 0 taken 448054 times.
✓ Branch 1 taken 422844 times.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 447994 times.
✓ Branch 4 taken 211952 times.
✓ Branch 5 taken 210952 times.
✓ Branch 6 taken 211512 times.
✓ Branch 7 taken 440 times.
✓ Branch 8 taken 432 times.
✓ Branch 9 taken 210960 times.
1293802 if ((numif != prevnumif || single_line_for_tracker == 3) && (whilestatus[numif].iswhile || whilestatus[numif].is_for) && whilestatus[numif].cond)
704 210960 i = whilestatus[numif].startline - 1;
705 871400 }
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 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 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 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
1/2
✓ Branch 0 taken 380 times.
✗ Branch 1 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
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 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
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 builtindefines.create("assembler_ver") = dec(get_version_int());
775
776
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
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 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 11020 define_name += *pos;
789 11020 pos++;
790 }
791
2/2
✓ Branch 0 taken 760 times.
✓ Branch 1 taken 380 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 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
1/2
✓ Branch 0 taken 1140 times.
✗ Branch 1 not taken.
1140 define_name = strip_whitespace(define_name);
800
1/2
✓ Branch 0 taken 1140 times.
✗ Branch 1 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 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
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
✗ Branch 2 not taken.
✗ Branch 3 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
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 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 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
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
✗ Branch 2 not taken.
✗ Branch 3 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
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 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 285 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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 570 times.
570 cleaned_defval = string(defval, (int)(defval_end - defval + 1));
851
852
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 570 times.
✗ Branch 2 not taken.
✗ Branch 3 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
1/2
✓ Branch 0 taken 570 times.
✗ Branch 1 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 1900 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 190 }
995