asar coverage - build #76


src/asar/
File: src/asar/main.cpp
Date: 2024-01-18 11:25:05
Lines:
391/470
83.2%
Functions:
18/22
81.8%
Branches:
388/635
61.1%

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 23 bool setmapper()
67 {
68 int maxscore=-99999;
69 mapper_t bestmap=lorom;
70 23 mapper_t maps[]={lorom, hirom, exlorom, exhirom};
71
2/2
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 23 times.
115 for (size_t mapid=0;mapid<sizeof(maps)/sizeof(maps[0]);mapid++)
72 {
73 92 mapper=maps[mapid];
74 int score=0;
75 int highbits=0;
76 bool foundnull=false;
77
2/2
✓ Branch 0 taken 1932 times.
✓ Branch 1 taken 92 times.
2024 for (int i=0;i<21;i++)
78 {
79 1932 unsigned char c=romdata[snestopc(0x00FFC0+i)];
80
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1932 times.
1932 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 1932 times.
1932 if (c>=128) highbits++;
82
2/2
✓ Branch 0 taken 330 times.
✓ Branch 1 taken 1602 times.
1932 else if (is_upper(c)) score+=3;
83
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 1470 times.
1602 else if (c==' ') score+=2;
84
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1470 times.
1470 else if (is_digit(c)) score+=1;
85
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1470 times.
1470 else if (is_lower(c)) score+=1;
86
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1470 times.
1470 else if (c=='-') score+=1;
87
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1470 times.
1470 else if (!c) foundnull=true;
88 else score-=3;
89 }
90
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 92 times.
92 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 23 times.
✓ Branch 1 taken 69 times.
92 if ((romdata[snestopc(0x00FFDE)]^romdata[snestopc(0x00FFDC)])!=0xFF ||
92
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 (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 23 times.
✓ Branch 1 taken 69 times.
92 if (score>maxscore)
95 {
96 maxscore=score;
97 bestmap=mapper;
98 }
99 }
100 23 mapper=bestmap;
101
102 //detect oddball mappers
103 23 int mapperbyte=romdata[snestopc(0x00FFD5)];
104 23 int romtypebyte=romdata[snestopc(0x00FFD6)];
105
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 if (mapper==lorom)
106 {
107
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
23 if (mapperbyte==0x23 && (romtypebyte==0x32 || romtypebyte==0x34 || romtypebyte==0x35)) mapper=sa1rom;
108 }
109 23 return (maxscore>=0);
110 }
111
112 93 string getdecor()
113 {
114 93 string e;
115
1/2
✓ Branch 0 taken 93 times.
✗ Branch 1 not taken.
93 if (thisfilename)
116 {
117 93 e+=STR thisfilename;
118
1/2
✓ Branch 0 taken 93 times.
✗ Branch 1 not taken.
186 if (thisline!=-1) e+=STR ":"+dec(thisline+1);
119
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 79 times.
107 if (callerfilename) e+=STR" (called from "+callerfilename+":"+dec(callerline+1)+")";
120 93 e+=": ";
121 }
122 93 return e;
123 }
124
125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 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 3 virtual_file_error asar_get_last_io_error()
145 {
146
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (filesystem != nullptr)
147 {
148 3 return filesystem->get_last_error();
149 }
150
151 return vfe_unknown;
152 }
153
154 static bool freespaced;
155 259 static int getlenforlabel(int insnespos, int thislabel, bool exists)
156 {
157
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 259 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
259 if (warnxkas && (((unsigned int)(thislabel^insnespos)&0xFFFF0000)==0))
158 asar_throw_warning(1, warning_id_xkas_label_access);
159 259 unsigned int bank = thislabel>>16;
160 259 unsigned int word = thislabel&0xFFFF;
161 259 unsigned int relaxed_bank = optimizeforbank < 0 ? 0 : optimizeforbank;
162
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 220 times.
259 if (!exists)
163 {
164
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 5 times.
39 if (!freespaced) freespaceextra++;
165 39 freespaced=true;
166 39 return 2;
167 }
168
5/6
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 214 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
220 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 9 times.
✓ Branch 1 taken 208 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 6 times.
217 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 6 times.
✓ Branch 1 taken 205 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
211 else if (optimize_address == optimize_address_flag::RAM && bank == 0x7E && word < 0x2000)
177 {
178 return 2;
179 }
180
6/10
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 205 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
208 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 205 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.
205 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 2 times.
✓ Branch 1 taken 203 times.
205 else if (optimizeforbank>=0)
189 {
190
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if ((unsigned int)thislabel&0xFF000000) return 3;
191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (bank==(unsigned int)optimizeforbank) return 2;
192 else return 3;
193 }
194
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 192 times.
203 else if ((unsigned int)(thislabel|insnespos)&0xFF000000)
195 {
196
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7 times.
11 if ((unsigned int)(thislabel^insnespos)&0xFF000000) return 3;
197 else return 2;
198 }
199
2/2
✓ Branch 0 taken 182 times.
✓ Branch 1 taken 10 times.
192 else if ((thislabel^insnespos)&0xFF0000){ return 3; }
200 else { return 2;}
201 }
202
203
204 1572 bool is_hex_constant(const char* str){
205
2/2
✓ Branch 0 taken 1336 times.
✓ Branch 1 taken 236 times.
1572 if (*str=='$')
206 {
207 1336 str++;
208
2/2
✓ Branch 0 taken 4626 times.
✓ Branch 1 taken 1336 times.
5962 while(is_xdigit(*str)) {
209 4626 str++;
210 }
211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1336 times.
1336 if(*str=='\0'){
212 return true;
213 }
214 }
215 return false;
216 }
217
218 1443 int getlen(const char * orgstr, bool optimizebankextraction)
219 {
220 1443 const char * str=orgstr;
221 1443 freespaced=false;
222
223 1443 const char* posneglabel = str;
224 1443 string posnegname = posneglabelname(&posneglabel, false);
225
226
2/2
✓ Branch 0 taken 1410 times.
✓ Branch 1 taken 33 times.
1443 if (posnegname.length() > 0)
227 {
228
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 30 times.
33 if (*posneglabel != '\0') goto notposneglabel;
229
230
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
50 if (!pass) return 2;
231 snes_label label_data;
232 // RPG Hacker: Umm... what kind of magic constant is this?
233 20 label_data.pos = 31415926;
234
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 bool found = labelval(posnegname, &label_data);
235
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 return getlenforlabel(snespos, (int)label_data.pos, found);
236 }
237 1410 notposneglabel:
238 int len=0;
239
2/2
✓ Branch 0 taken 1486 times.
✓ Branch 1 taken 1413 times.
2899 while (*str)
240 {
241 int thislen=0;
242 1486 bool maybebankextraction=(str==orgstr);
243
2/2
✓ Branch 0 taken 1132 times.
✓ Branch 1 taken 354 times.
1486 if (*str=='$')
244 {
245 1132 str++;
246 int i;
247
2/2
✓ Branch 0 taken 4386 times.
✓ Branch 1 taken 1132 times.
5518 for (i=0;is_xdigit(str[i]);i++);
248 //if (i&1) warn(S dec(i)+"-digit hex value");//blocked in getnum instead
249 1132 thislen=(i+1)/2;
250 1132 str+=i;
251 }
252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 354 times.
354 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 354 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
354 else if (str[0]=='\'' && str[2]=='\'')
262 {
263 thislen=1;
264 str+=3;
265 }
266
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 292 times.
354 else if (is_digit(*str))
267 {
268 62 int val=strtol(str, const_cast<char**>(&str), 10);
269
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 if (val>=0) thislen=1;
270
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 9 times.
62 if (val>=256) thislen=2;
271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (val>=65536) thislen=3;
272 if (val>=16777216) thislen=4;
273 }
274
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 239 times.
292 else if (is_alpha(*str) || *str=='_' || *str=='.' || *str=='?')
275 {
276 snes_label thislabel;
277
1/2
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
239 bool exists=labelval(&str, &thislabel);
278
1/2
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
239 thislen=getlenforlabel(snespos, (int)thislabel.pos, exists);
279 }
280 53 else str++;
281
2/2
✓ Branch 0 taken 158 times.
✓ Branch 1 taken 1328 times.
1486 if (optimizebankextraction && maybebankextraction &&
282
3/6
✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 158 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 158 times.
✗ Branch 5 not taken.
158 (!strcmp(str, ">>16") || !strcmp(str, "/65536") || !strcmp(str, "/$10000")))
283 return 1;
284 if (thislen>len) len=thislen;
285 }
286 1413 if (len>3) return 3;
287 return len;
288 1443 }
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 856 bool validatedefinename(const char * name)
316 {
317
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 856 times.
856 if (!name[0]) return false;
318
2/2
✓ Branch 0 taken 8599 times.
✓ Branch 1 taken 856 times.
9455 for (int i = 0;name[i];i++)
319 {
320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8599 times.
8599 if (!is_ualnum(name[i])) return false;
321 }
322
323 return true;
324 }
325
326 753118 void resolvedefines(string& out, const char * start)
327 {
328 753118 recurseblock rec;
329 const char * here=start;
330
2/2
✓ Branch 0 taken 4306843 times.
✓ Branch 1 taken 753111 times.
5059954 while (*here)
331 {
332
4/4
✓ Branch 0 taken 1563 times.
✓ Branch 1 taken 4305280 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1557 times.
4306843 if (*here=='"' && emulatexkas)
333 {
334
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 asar_throw_warning(0, warning_id_feature_deprecated, "xkas define quotes", "removing the quotes generally does what you want");
335 6 out+=*here++;
336
3/4
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 6 times.
24 while (*here && *here!='"') out+=*here++;
337 6 out+=*here++;
338 }
339
4/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 4306813 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 21 times.
4306837 else if (here[0] == '\\' && here[1] == '\\')
340 {
341 // allow using \\ as escape sequence
342 3 out += "\\";
343 3 here += 2;
344 }
345
4/4
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 4306813 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 6 times.
4306834 else if (here[0] == '\\' && here[1] == '!')
346 {
347 // allow using \! to escape !
348 15 out+="!";
349 15 here += 2;
350 }
351
2/2
✓ Branch 0 taken 317598 times.
✓ Branch 1 taken 3989221 times.
4306819 else if (*here=='!')
352 {
353
7/10
✓ Branch 0 taken 106392 times.
✓ Branch 1 taken 211206 times.
✓ Branch 2 taken 105612 times.
✓ Branch 3 taken 780 times.
✓ Branch 4 taken 105513 times.
✓ Branch 5 taken 99 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 105513 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
317598 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 317598 here++;
356
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 317544 times.
317598 if (*here=='{')
357 {
358 54 here++;
359 54 string unprocessedname;
360 int braces=1;
361 while (true)
362 {
363
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 540 times.
576 if (*here=='{') braces++;
364
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 486 times.
576 if (*here=='}') braces--;
365
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 576 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
576 if (!*here) asar_throw_error(0, error_type_line, error_id_mismatched_braces);
366
2/2
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 54 times.
576 if (!braces) break;
367 522 unprocessedname+=*here++;
368 }
369
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 here++;
370
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 resolvedefines(defname, unprocessedname);
371
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
54 if (!validatedefinename(defname)) asar_throw_error(0, error_type_line, error_id_invalid_define_name);
372 54 }
373 else
374 {
375
2/2
✓ Branch 0 taken 327414 times.
✓ Branch 1 taken 317544 times.
644958 while (is_ualnum(*here)) defname+=*here++;
376 }
377
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 317598 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
317598 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 211206 times.
✓ Branch 1 taken 106392 times.
317598 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 135 times.
✓ Branch 1 taken 211071 times.
211206 else if (stribegin(here, " = ")) { here+=3; mode=null; }
392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 211071 times.
211071 else if (stribegin(here, " += ")) { here+=4; mode=append; }
393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 211071 times.
211071 else if (stribegin(here, " := ")) { here+=4; mode=expand; }
394
2/2
✓ Branch 0 taken 105483 times.
✓ Branch 1 taken 105588 times.
211071 else if (stribegin(here, " #= ")) { here+=4; mode=domath; }
395
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 105585 times.
105588 else if (stribegin(here, " ?= ")) { here+=4; mode=setifnotset; }
396 105585 else goto notdefineset;
397
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 105621 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
105621 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 21 times.
✓ Branch 1 taken 105600 times.
105621 if (*here=='"')
401 {
402 21 here++;
403 while (true)
404 {
405
2/2
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 24 times.
147 if (*here=='"')
406 {
407
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
24 if (!here[1] || here[1]==' ') break;
408
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 else if (here[1]=='"') here++;
409 else asar_throw_error(0, error_type_line, error_id_broken_define_declaration);
410 }
411 126 val+=*here++;
412 }
413 21 here++;
414 }
415 else
416 {
417
3/4
✓ Branch 0 taken 424368 times.
✓ Branch 1 taken 105600 times.
✓ Branch 2 taken 424368 times.
✗ Branch 3 not taken.
529968 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 105621 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
105621 if (*here && !stribegin(here, " : ")) asar_throw_error(0, error_type_line, error_id_broken_define_declaration);
421
4/8
✓ Branch 0 taken 105621 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 105621 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 105621 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 105621 times.
✗ Branch 7 not taken.
105621 clean(val);
422
423 // RPG Hacker: throw an error if we're trying to overwrite built-in defines.
424
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 105618 times.
105621 if (builtindefines.exists(defname))
425 {
426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 asar_throw_error(0, error_type_line, error_id_overriding_builtin_define, defname.data());
427 }
428
429
3/5
✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 105483 times.
✓ Branch 4 taken 3 times.
105618 switch (mode)
430 {
431 case null:
432 {
433
1/2
✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
132 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 105483 times.
✗ Branch 1 not taken.
105483 resolvedefines(newval, val);
455
1/2
✓ Branch 0 taken 105483 times.
✗ Branch 1 not taken.
105483 double num= getnumdouble(newval);
456
5/6
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 105477 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
105483 if (foundlabel && !foundlabel_static) asar_throw_error(0, error_type_line, error_id_define_label_math);
457
1/2
✓ Branch 0 taken 105480 times.
✗ Branch 1 not taken.
105480 defines.create(defname) = ftostr(num);
458 break;
459 105483 }
460 case setifnotset:
461 {
462
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 if (!defines.exists(defname)) defines.create(defname) = val;
463 break;
464 }
465 }
466 105621 }
467 else
468 {
469 106392 notdefineset:
470
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 211965 times.
211977 if (!defname) out+="!";
471 else
472 {
473
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 211965 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
211965 if (!defines.exists(defname)) asar_throw_error(0, error_type_line, error_id_define_not_found, defname.data());
474 else {
475 211965 string thisone = defines.find(defname);
476
1/2
✓ Branch 0 taken 211965 times.
✗ Branch 1 not taken.
211965 resolvedefines(out, thisone);
477 211965 }
478 }
479 }
480 317598 }
481 3989221 else out+=*here++;
482 }
483 753117 }
484
485 int repeatnext=1;
486
487 bool moreonline;
488 bool moreonlinecond;
489 int fakeendif;
490 bool asarverallowed;
491 bool istoplevel;
492
493 436216 void assembleline(const char * fname, int linenum, const char * line)
494 {
495 436216 recurseblock rec;
496 436216 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 436216 thisline=linenum;
502 436216 thisblock= nullptr;
503 436216 single_line_for_tracker = 1;
504 try
505 {
506 436216 string tmp;
507
4/4
✓ Branch 0 taken 516 times.
✓ Branch 1 taken 435700 times.
✓ Branch 2 taken 495 times.
✓ Branch 3 taken 21 times.
436216 if(inmacro) tmp = replace_macro_args(line);
508 else tmp = line;
509
4/8
✓ Branch 0 taken 436195 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 436195 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 436195 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 436195 times.
✗ Branch 7 not taken.
436195 clean(tmp);
510 436195 string out;
511
4/4
✓ Branch 0 taken 435442 times.
✓ Branch 1 taken 753 times.
✓ Branch 2 taken 435435 times.
✓ Branch 3 taken 7 times.
436195 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 436188 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 436185 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
436188 if (!confirmquotes(out)) asar_throw_error(0, error_type_line, error_id_mismatched_quotes);
515
1/2
✓ Branch 0 taken 436185 times.
✗ Branch 1 not taken.
436185 out.qreplace(": :", ": :", true);
516 //puts(out);
517
1/2
✓ Branch 0 taken 436185 times.
✗ Branch 1 not taken.
436185 autoptr<char**> blocks=qsplit(out.temp_raw(), " : ");
518 436185 moreonline=true;
519 436185 moreonlinecond=true;
520 436185 fakeendif=0;
521
2/2
✓ Branch 0 taken 436992 times.
✓ Branch 1 taken 435935 times.
872927 for (int block=0;moreonline;block++)
522 {
523 436992 moreonline=(blocks[block+1] != nullptr);
524 436992 int repeatthis=repeatnext;
525 436992 repeatnext=1;
526
2/2
✓ Branch 0 taken 436992 times.
✓ Branch 1 taken 436742 times.
873734 for (int i=0;i<repeatthis;i++)
527 {
528 try
529 {
530 436992 string stripped_block = blocks[block];
531
1/2
✓ Branch 0 taken 436992 times.
✗ Branch 1 not taken.
436992 strip_both(stripped_block, ' ', true);
532
533
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 436986 times.
436992 thisline=linenum;//do not optimize, this one is recursive
534 436992 thisblock = stripped_block.data();
535 bool isspecialline = false;
536
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 436986 times.
436992 if (thisblock[0] == '@')
537 {
538
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 asar_throw_warning(0, warning_id_feature_deprecated, "prefixing Asar commands with @ or ;@", "remove the @ or ;@ prefix");
539
540 isspecialline = true;
541 6 thisblock++;
542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 while (is_space(*thisblock))
543 {
544 thisblock++;
545 }
546 }
547
2/2
✓ Branch 0 taken 436663 times.
✓ Branch 1 taken 329 times.
436992 assembleblock(thisblock, isspecialline);
548
2/2
✓ Branch 0 taken 436662 times.
✓ Branch 1 taken 1 times.
436663 checkbankcross();
549 436992 }
550
2/2
✓ Branch 0 taken 250 times.
✓ Branch 1 taken 80 times.
330 catch (errblock&) {}
551
4/4
✓ Branch 0 taken 326235 times.
✓ Branch 1 taken 110507 times.
✓ Branch 2 taken 326229 times.
✓ Branch 3 taken 6 times.
436742 if (blocks[block][0]!='\0' && blocks[block][0]!='@') asarverallowed=false;
552 }
553
2/2
✓ Branch 0 taken 435731 times.
✓ Branch 1 taken 1011 times.
436742 if(single_line_for_tracker == 1) single_line_for_tracker = 0;
554 }
555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 435935 times.
435935 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 436726 }
564
2/2
✓ Branch 0 taken 251 times.
✓ Branch 1 taken 30 times.
281 catch (errline&) {}
565 435965 moreonline=moreonlinetmp;
566 436467 }
567
568 int incsrcdepth=0;
569
570 // Returns true if a file is protected via
571 // an "includeonce".
572 605 bool file_included_once(const char* file)
573 {
574
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 584 times.
704 for (int i = 0; i < includeonce.count; ++i)
575 {
576
2/2
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 21 times.
120 if (includeonce[i] == file)
577 {
578 return true;
579 }
580 }
581
582 return false;
583 }
584
585 590 void assemblefile(const char * filename, bool toplevel)
586 {
587 590 incsrcdepth++;
588 590 string absolutepath = filesystem->create_absolute_path(thisfilename, filename);
589
590
2/2
✓ Branch 0 taken 569 times.
✓ Branch 1 taken 21 times.
590 if (file_included_once(absolutepath))
591 {
592 return;
593 }
594
595 569 string prevthisfilename = thisfilename;
596 thisfilename = absolutepath;
597 569 int prevline = thisline;
598 569 thisline=-1;
599 569 const char* prevthisblock = thisblock;
600 569 thisblock= nullptr;
601 sourcefile file;
602 569 file.contents = nullptr;
603 569 file.numlines = 0;
604
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 459 times.
569 int startif=numif;
605
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 459 times.
569 if (!filecontents.exists(absolutepath))
606 {
607
1/2
✓ Branch 0 taken 110 times.
✗ Branch 1 not taken.
110 char * temp= readfile(absolutepath, "");
608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
110 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 110 times.
✗ Branch 1 not taken.
110 file.contents =split(temp, "\n");
621
2/2
✓ Branch 0 taken 4506 times.
✓ Branch 1 taken 110 times.
4616 for (int i=0;file.contents[i];i++)
622 {
623 4506 file.numlines++;
624 char * line= file.contents[i];
625 char * comment=line;
626 4506 comment = strqchr(comment, ';');
627
2/2
✓ Branch 0 taken 1234 times.
✓ Branch 1 taken 4506 times.
5740 while (comment != nullptr)
628 {
629 1234 const char* comment_end = comment + strlen(comment);
630
2/2
✓ Branch 0 taken 1231 times.
✓ Branch 1 taken 3 times.
1234 if (comment_end - comment >= 2
631
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1231 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1231 && 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 1232 times.
✓ Branch 1 taken 2 times.
1234 if (comment[1]!='@')
638 {
639 1232 comment[0]='\0';
640 }
641 else
642 {
643 2 comment[0] = ' ';
644 }
645 1234 comment = strqchr(comment, ';');
646 }
647
2/2
✓ Branch 0 taken 699 times.
✓ Branch 1 taken 4506 times.
5205 while (strqchr(line, '\t')) *strqchr(line, '\t')=' ';
648
4/6
✓ Branch 0 taken 4506 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4505 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
4506 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 4506 times.
✗ Branch 1 not taken.
4506 itrim(line, " ", " ", true); //todo make use strip
650 }
651
2/2
✓ Branch 0 taken 4506 times.
✓ Branch 1 taken 110 times.
4616 for(int i=0;file.contents[i];i++)
652 {
653 char* line = file.contents[i];
654
5/6
✓ Branch 0 taken 661 times.
✓ Branch 1 taken 3850 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 656 times.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
4511 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 5 char* line_end = line + strlen(line);
659
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 5 times.
69 while(*otherline) *line_end++ = *otherline++;
660 5 *line_end = '\0';
661 static char nullstr[]="";
662 5 file.contents[i+j]=nullstr;
663 }
664 }
665
1/2
✓ Branch 0 taken 110 times.
✗ Branch 1 not taken.
110 filecontents.create(absolutepath) = file;
666 } else { // filecontents.exists(absolutepath)
667 459 file = filecontents.find(absolutepath);
668 }
669 bool in_macro_def=false;
670 569 asarverallowed=true;
671
3/4
✓ Branch 0 taken 436048 times.
✓ Branch 1 taken 318 times.
✓ Branch 2 taken 436048 times.
✗ Branch 3 not taken.
436366 for (int i=0;file.contents[i] && i<file.numlines;i++)
672 {
673 try
674 {
675 thisfilename= absolutepath;
676 436048 thisline=i;
677 436048 thisblock= nullptr;
678 436048 istoplevel=toplevel;
679
3/4
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 435970 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 78 times.
436048 if (stribegin(file.contents[i], "macro ") && numif==numtrue)
680 {
681
2/6
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 78 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
78 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 26 times.
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 1 times.
78 if (!pass) startmacro(file.contents[i]+6);
684 }
685
3/4
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 435892 times.
✓ Branch 2 taken 78 times.
✗ Branch 3 not taken.
435970 else if (!stricmp(file.contents[i], "endmacro") && numif==numtrue)
686 {
687
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
78 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 26 times.
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
78 if (!pass) endmacro(true);
690 }
691
2/2
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 435700 times.
435892 else if (in_macro_def)
692 {
693
3/4
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 64 times.
✗ Branch 3 not taken.
192 if (!pass) tomacro(file.contents[i]);
694 }
695 else
696 {
697 435700 int prevnumif = numif;
698 435700 string connectedline;
699 435700 int skiplines = getconnectedlines<char**>(file.contents, i, connectedline);
700
2/2
✓ Branch 0 taken 435449 times.
✓ Branch 1 taken 251 times.
435700 assembleline(absolutepath, i, connectedline);
701 thisfilename = absolutepath;
702 435449 i += skiplines;
703
10/10
✓ Branch 0 taken 224027 times.
✓ Branch 1 taken 211422 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 223997 times.
✓ Branch 4 taken 105976 times.
✓ Branch 5 taken 105476 times.
✓ Branch 6 taken 105756 times.
✓ Branch 7 taken 220 times.
✓ Branch 8 taken 216 times.
✓ Branch 9 taken 105480 times.
646901 if ((numif != prevnumif || single_line_for_tracker == 3) && (whilestatus[numif].iswhile || whilestatus[numif].is_for) && whilestatus[numif].cond)
704 105480 i = whilestatus[numif].startline - 1;
705 435700 }
706 }
707
2/2
✓ Branch 0 taken 251 times.
✓ Branch 1 taken 1 times.
252 catch (errline&) {}
708 }
709 318 thisline++;
710 318 thisblock= nullptr;
711
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 318 times.
318 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 318 times.
318 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 318 times.
318 if (numif!=startif)
722 {
723 numif=startif;
724 numtrue=startif;
725 asar_throw_error(0, error_type_null, error_id_unclosed_if);
726 }
727 318 incsrcdepth--;
728 841 }
729
730 95 void parse_std_includes(const char* textfile, autoarray<string>& outarray)
731 {
732 95 char* content = readfilenative(textfile);
733
734
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 if (content != nullptr)
735 {
736 char* pos = content;
737
738
2/2
✓ Branch 0 taken 190 times.
✓ Branch 1 taken 95 times.
285 while (pos[0] != '\0')
739 {
740 190 string stdinclude;
741
742 do
743 {
744
3/4
✓ Branch 0 taken 3610 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3515 times.
✓ Branch 3 taken 95 times.
3610 if (pos[0] != '\r' && pos[0] != '\n')
745 {
746 3515 stdinclude += pos[0];
747 }
748 3610 pos++;
749
4/4
✓ Branch 0 taken 3515 times.
✓ Branch 1 taken 95 times.
✓ Branch 2 taken 3420 times.
✓ Branch 3 taken 95 times.
3610 } while (pos[0] != '\0' && pos[0] != '\n');
750
751
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 stdinclude = strip_whitespace(stdinclude);
752
753
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 95 times.
190 if (stdinclude != "")
754 {
755
2/4
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 95 times.
95 if (!path_is_absolute(stdinclude))
756 {
757 stdinclude = dir(textfile) + stdinclude;
758 }
759
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 outarray.append(normalize_path(stdinclude));
760 }
761 190 }
762
763 95 free(content);
764 }
765 95 }
766
767 95 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 95 builtindefines.create("assembler") = "asar";
774
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 builtindefines.create("assembler_ver") = dec(get_version_int());
775
776
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 if(textfile == nullptr) return;
777
778 95 char* content = readfilenative(textfile);
779
780
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 if (content != nullptr)
781 {
782 char* pos = content;
783
2/2
✓ Branch 0 taken 570 times.
✓ Branch 1 taken 95 times.
665 while (*pos != 0) {
784 570 string define_name;
785 570 string define_val;
786
787
4/4
✓ Branch 0 taken 5700 times.
✓ Branch 1 taken 380 times.
✓ Branch 2 taken 5510 times.
✓ Branch 3 taken 190 times.
6080 while (*pos != '=' && *pos != '\n') {
788 5510 define_name += *pos;
789 5510 pos++;
790 }
791
2/2
✓ Branch 0 taken 380 times.
✓ Branch 1 taken 190 times.
570 if (*pos != 0 && *pos != '\n') pos++; // skip =
792
3/4
✓ Branch 0 taken 2565 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1995 times.
✓ Branch 3 taken 570 times.
2565 while (*pos != 0 && *pos != '\n') {
793 1995 define_val += *pos;
794 1995 pos++;
795 }
796
1/2
✓ Branch 0 taken 570 times.
✗ Branch 1 not taken.
570 if (*pos != 0)
797 570 pos++; // skip \n
798 // clean define_name
799
1/2
✓ Branch 0 taken 570 times.
✗ Branch 1 not taken.
570 define_name = strip_whitespace(define_name);
800
1/2
✓ Branch 0 taken 570 times.
✗ Branch 1 not taken.
570 define_name = strip_prefix(define_name, '!', false); // remove leading ! if present
801
802
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 475 times.
570 if (define_name == "")
803 {
804
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 if (define_val == "")
805 {
806 95 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 475 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
475 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 95 times.
✓ Branch 1 taken 380 times.
475 if (*defval == 0) {
819 // no value
820
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
95 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 95 times.
✗ Branch 1 not taken.
95 clidefines.create(define_name) = "";
822 95 continue;
823 }
824
825
3/4
✓ Branch 0 taken 190 times.
✓ Branch 1 taken 380 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 380 times.
570 while (*defval == ' ' || *defval == '\t') defval++; // skip whitespace in beginning
826
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 285 times.
380 if (*defval == '"') {
827 95 defval++; // skip opening quote
828
3/4
✓ Branch 0 taken 1235 times.
✓ Branch 1 taken 95 times.
✓ Branch 2 taken 1235 times.
✗ Branch 3 not taken.
1330 while (*defval != '"' && *defval != 0)
829 1235 cleaned_defval += *defval++;
830
831
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
95 if (*defval == 0) {
832 asar_throw_error(pass, error_type_null, error_id_mismatched_quotes);
833 }
834 95 defval++; // skip closing quote
835
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 95 times.
95 while (*defval == ' ' || *defval == '\t') defval++; // skip whitespace
836
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
95 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 95 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
95 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 95 times.
✗ Branch 1 not taken.
95 clidefines.create(define_name) = cleaned_defval;
841 95 continue;
842 }
843 else
844 {
845 // slightly hacky way to remove trailing whitespace
846 const char* defval_end = strchr(defval, '\n'); // slightly hacky way to get end of string or newline
847
1/2
✓ Branch 0 taken 285 times.
✗ Branch 1 not taken.
285 if (!defval_end) defval_end = strchr(defval, 0);
848 285 defval_end--;
849
3/4
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 285 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 285 times.
380 while (*defval_end == ' ' || *defval_end == '\t') defval_end--;
850
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 285 times.
285 cleaned_defval = string(defval, (int)(defval_end - defval + 1));
851
852
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 285 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
285 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 285 times.
✗ Branch 1 not taken.
285 clidefines.create(define_name) = cleaned_defval;
854 285 continue;
855 285 }
856
857 570 }
858 95 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 26 static void clearmacro(const string & key, macrodata* & macro)
867 {
868 (void)key;
869 26 macro->lines.~autoarray();
870 26 cfree(macro->fname);
871 26 cfree(macro->arguments[0]);
872 26 cfree(macro->arguments);
873 26 cfree(macro);
874 26 }
875
876 110 static void clearfile(const string & key, sourcefile& filecontent)
877 {
878 (void)key;
879 110 cfree(*filecontent.contents);
880 110 cfree(filecontent.contents);
881 110 }
882
883
1/2
✓ Branch 0 taken 950 times.
✗ Branch 1 not taken.
950 static void adddefine(const string & key, string & value)
884 {
885
1/2
✓ Branch 0 taken 950 times.
✗ Branch 1 not taken.
950 if (!defines.exists(key)) defines.create(key) = value;
886 950 }
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 95 void reseteverything()
961 {
962 95 string str;
963 95 labels.reset();
964 95 defines.reset();
965
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 builtindefines.each(adddefine);
966
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 clidefines.each(adddefine);
967 95 structs.reset();
968
969
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 macros.each(clearmacro);
970 95 macros.reset();
971
972
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 filecontents.each(clearfile);
973 95 filecontents.reset();
974
975 95 writtenblocks.reset();
976
977 95 optimizeforbank=-1;
978 95 optimize_dp = optimize_dp_flag::NONE;
979 95 dp_base = 0;
980 95 optimize_address = optimize_address_flag::DEFAULT;
981
982
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 closecachedfiles();
983
984 95 incsrcdepth=0;
985 95 errored = false;
986 95 checksum_fix_enabled = true;
987 95 force_checksum_fix = false;
988
989 95 default_math_pri = false;
990 95 default_math_round_off = false;
991 95 suppress_all_warnings = false;
992
993 #undef free
994 95 }
995