asar coverage - build #319


src/asar/
File: src/asar/assembleblock.cpp
Date: 2025-09-21 04:11:32
Lines:
1301/1415
91.9%
Functions:
130/135
96.3%
Branches:
1986/3299
60.2%

Line Branch Exec Source
1 #include "addr2line.h"
2 #include "asar.h"
3 #include "assembleblock.h"
4 #include "asar_math.h"
5 #include "macro.h"
6 #include "table.h"
7 #include "unicode.h"
8 #include "frozen/string.h"
9 #include "frozen/unordered_map.h"
10
11 #include "interface-shared.h"
12 #include "arch-shared.h"
13
14 int arch=arch_65816;
15
16 bool snespos_valid = false;
17 int snespos;
18 int realsnespos;
19 int startpos;
20 int realstartpos;
21
22 static bool mapper_set = false;
23 int label_counter = 0;
24
25 static int old_snespos;
26 static int old_startpos;
27 static int old_optimizeforbank;
28 static bool old_snespos_valid;
29 static int struct_base;
30 static string struct_name;
31 static string struct_parent;
32 static bool in_struct = false;
33 static bool in_sub_struct = false;
34 static bool static_struct = false;
35 static bool in_spcblock = false;
36
37 assocarr<snes_struct> structs;
38
39 static bool movinglabelspossible = false;
40
41 static bool disable_bank_cross_errors = false;
42 static bool check_half_banks_crossed = false;
43
44 int bytes;
45 static int freespaceuse=0;
46
47 static enum {
48 ratsmeta_ban,
49 ratsmeta_allow,
50 ratsmeta_used,
51 } ratsmetastate=ratsmeta_ban;
52
53 enum spcblock_type{
54 spcblock_nspc,
55 spcblock_custom
56 };
57
58 static struct spcblock_data{
59 unsigned int destination;
60 spcblock_type type;
61 string macro_name;
62
63 unsigned int size_address;
64 mapper_t old_mapper;
65 }spcblock;
66
67 437903 static inline void verifysnespos()
68 {
69
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 437903 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 219046 times.
437903 if (!snespos_valid)
70 {
71 throw_err_block(0, err_missing_org);
72 snespos=0x008000;
73 realsnespos=0x008000;
74 startpos=0x008000;
75 realstartpos=0x008000;
76 snespos_valid = true;
77 }
78 437903 }
79
80 552 static int fixsnespos(int inaddr, int step)
81 {
82 // randomdude999: turns out it wasn't very reliable at all.
83 /* // RPG Hacker: No idea how reliable this is.
84 // Might not work with some of the more exotic mappers.
85 return pctosnes(snestopc(inaddr) + step); */
86
4/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 504 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 228 times.
552 if (mapper == lorom) {
87
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 84 times.
96 if ((inaddr&0xFFFF)+step > 0xFFFF) {
88 // bank crossed
89 12 return inaddr+step+0x8000;
90 }
91 84 return inaddr+step;
92
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 456 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 228 times.
456 } else if (mapper == hirom) {
93 if ((inaddr&0x400000) == 0 && freespaceid == 0) {
94 // we shouldn't get here in pass 2 inside a freespace anyways i think
95 // system pages, need to account for low pages and stuff
96 if ((inaddr&0xFFFF)+step > 0xFFFF) {
97 return inaddr+step+0x8000;
98 }
99 }
100 return inaddr+step;
101
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 456 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 228 times.
456 } else if (mapper == exlorom) {
102 // exlorom has no mirroring so this should work fine
103 return pctosnes(snestopc(inaddr)+step);
104
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 456 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 228 times.
456 } else if (mapper == exhirom) {
105 // apparently exhirom is pretty similar to hirom after all
106 if ((inaddr&0x400000) == 0) {
107 // system pages, need to account for low pages and stuff
108 if ((inaddr&0xFFFF)+step > 0xFFFF) {
109 return inaddr+step+0x8000;
110 }
111 }
112 return inaddr+step;
113
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 456 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 228 times.
456 } else if (mapper == sa1rom) {
114 if((inaddr&0x400000) == 0) {
115 // lorom area
116 if ((inaddr&0xFFFF)+step > 0xFFFF) {
117 return inaddr+step+0x8000;
118 }
119 return inaddr+step;
120 } else {
121 // hirom area
122 return inaddr+step;
123 }
124
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 456 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 228 times.
456 } else if (mapper == sfxrom) {
125 if ((inaddr&0x400000) == 0) {
126 // lorom area
127 if ((inaddr&0xFFFF)+step > 0xFFFF) {
128 return inaddr+step+0x8000;
129 }
130 } else {
131 // hirom area
132 return inaddr+step;
133 }
134
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 456 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 228 times.
456 } else if (mapper == bigsa1rom) {
135 // no mirrors here, so this should work
136 return pctosnes(snestopc(inaddr)+step);
137
3/4
✓ Branch 0 taken 228 times.
✓ Branch 1 taken 228 times.
✓ Branch 2 taken 228 times.
✗ Branch 3 not taken.
456 } else if (mapper == norom) {
138 456 return inaddr+step;
139 }
140 return -1;
141 }
142
143 437432 static inline void step(int num)
144 {
145
4/4
✓ Branch 0 taken 138 times.
✓ Branch 1 taken 437294 times.
✓ Branch 2 taken 138 times.
✓ Branch 3 taken 218662 times.
437432 if (disable_bank_cross_errors)
146 {
147 276 snespos = fixsnespos(snespos, num);
148 276 realsnespos = fixsnespos(realsnespos, num);
149
150 // RPG Hacker: Not adjusting startpos here will eventually throw
151 // an error in checkbankcross() if we set warn bankcross on again.
152 // As far as I can tell, those are pretty much just used for
153 // checking bank crossing, anyways, so it's hopefully save to just
154 // adjust them here.
155 276 startpos = snespos;
156 276 realstartpos = realsnespos;
157 }
158 else
159 {
160 437156 snespos += num;
161 437156 realsnespos += num;
162 }
163 437432 bytes+=num;
164 437432 }
165
166 436814 void write1(unsigned int num)
167 {
168 436814 verifysnespos();
169
2/2
✓ Branch 0 taken 145576 times.
✓ Branch 1 taken 291238 times.
436814 if (pass==2)
170 {
171 145576 int pcpos=snestopc(realsnespos&0xFFFFFF);
172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 145576 times.
145576 if (pcpos<0)
173 {
174 movinglabelspossible=true;
175 throw_err_block(2, err_snes_address_doesnt_map_to_rom, hex((unsigned int)realsnespos, 6).data());
176 }
177 145576 writeromdata_byte(pcpos, (unsigned char)num, freespaceid != 0);
178
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 145574 times.
145576 if (pcpos>=romlen) {
179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(pcpos - romlen > 0) writeromdata_bytes(romlen, freespacebyte, pcpos - romlen, false);
180 2 romlen=pcpos+1;
181 }
182 }
183
4/4
✓ Branch 0 taken 145618 times.
✓ Branch 1 taken 291196 times.
✓ Branch 2 taken 9164 times.
✓ Branch 3 taken 136454 times.
436814 if(pass == 1 && freespaceid == 0) {
184 9164 int pcpos = snestopc(realsnespos & 0xFFFFFF);
185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9164 times.
9164 if(pcpos < 0)
186 {
187 movinglabelspossible=true;
188 throw_err_block(2, err_snes_address_doesnt_map_to_rom, hex((unsigned int)realsnespos, 6).data());
189 }
190 9164 addromwrite(pcpos, 1);
191
2/2
✓ Branch 0 taken 8747 times.
✓ Branch 1 taken 417 times.
9164 if (pcpos>=romlen) {
192
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 8660 times.
8747 if(pcpos - romlen > 0) writeromdata_bytes(romlen, freespacebyte, pcpos - romlen, false);
193 8747 romlen=pcpos+1;
194 }
195 }
196 436814 step(1);
197 436814 ratsmetastate=ratsmeta_ban;
198 436814 }
199
200 31877 static bool asblock_pick(const string& firstword, const char* par)
201 {
202
6/6
✓ Branch 0 taken 29531 times.
✓ Branch 1 taken 2346 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 29516 times.
✓ Branch 4 taken 15 times.
✓ Branch 5 taken 14872 times.
31877 if (arch==arch_spc700 || in_spcblock) {
203 // TODO
204
2/3
✓ Branch 0 taken 1188 times.
✓ Branch 1 taken 1188 times.
✗ Branch 2 not taken.
2376 string dup(firstword);
205
2/3
✓ Branch 0 taken 1188 times.
✓ Branch 1 taken 1188 times.
✗ Branch 2 not taken.
2376 string duppar(par);
206 2376 char* words[] = { dup.raw(), duppar.raw() };
207
4/6
✓ Branch 0 taken 1128 times.
✓ Branch 1 taken 1188 times.
✓ Branch 2 taken 1248 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1188 times.
✗ Branch 5 not taken.
2376 return asblock_spc700(words, *par ? 2 : 1);
208 2376 }
209
2/2
✓ Branch 0 taken 25847 times.
✓ Branch 1 taken 3654 times.
29501 if (arch==arch_65816) {
210 25847 return asblock_65816(firstword, par);
211 }
212
1/2
✓ Branch 0 taken 3654 times.
✗ Branch 1 not taken.
3654 if (arch==arch_superfx) {
213
2/3
✓ Branch 0 taken 1827 times.
✓ Branch 1 taken 1827 times.
✗ Branch 2 not taken.
3654 string dup(firstword);
214
2/3
✓ Branch 0 taken 1827 times.
✓ Branch 1 taken 1827 times.
✗ Branch 2 not taken.
3654 string duppar(par);
215 3654 char* words[] = { dup.raw(), duppar.raw() };
216
4/6
✓ Branch 0 taken 1722 times.
✓ Branch 1 taken 1827 times.
✓ Branch 2 taken 1932 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1827 times.
✗ Branch 5 not taken.
3654 return asblock_superfx(words, *par ? 2 : 1);
217 3654 }
218 return true;
219 }
220
221 11527 const char * safedequote(char * str)
222 {
223 11527 const char * tmp=dequote(str);
224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11527 times.
11527 if (!tmp) throw_err_block(0, err_garbage_near_quoted_string);
225 11527 return tmp;
226 }
227
228 1855 void write2(unsigned int num)
229 {
230 1855 write1(num);
231 1855 write1(num/256);
232 1855 }
233
234 1210 void write3(unsigned int num)
235 {
236 1210 write1(num);
237 1210 write1(num/256);
238 1210 write1(num/65536);
239 1210 }
240
241 114 void write4(unsigned int num)
242 {
243 114 write1(num);
244 114 write1(num/256);
245 114 write1(num/65536);
246 114 write1(num/16777216);
247 114 }
248
249 //these are NOT used by the math parser - see asar_math.cpp for that
250 22 static int read2(int insnespos)
251 {
252 22 int addr=snestopc(insnespos);
253
2/4
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 22 times.
22 if (addr<0 || addr+2>romlen_r) return -1;
254 return
255 22 romdata_r[addr ] |
256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
33 (romdata_r[addr+1]<< 8);
257 }
258
259 54 static int read3(int insnespos)
260 {
261 54 int addr=snestopc(insnespos);
262
2/4
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
54 if (addr<0 || addr+3>romlen_r) return -1;
263 return
264 54 romdata_r[addr ] |
265 81 (romdata_r[addr+1]<< 8)|
266
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
81 (romdata_r[addr+2]<<16);
267 }
268
269 1452 int getlenfromchar(char c)
270 {
271 1452 c=(char)to_lower(c);
272
2/2
✓ Branch 0 taken 660 times.
✓ Branch 1 taken 792 times.
1452 if (c=='b') return 1;
273
2/2
✓ Branch 0 taken 690 times.
✓ Branch 1 taken 102 times.
792 if (c=='w') return 2;
274
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 6 times.
102 if (c=='l') return 3;
275 6 throw_err_block(0, err_invalid_opcode_length);
276 }
277
278 assocarr<snes_label> labels;
279 static autoarray<int> poslabels;
280 static autoarray<int> neglabels;
281
282 autoarray<int>* macroposlabels;
283 autoarray<int>* macroneglabels;
284
285 autoarray<string> sublabels;
286 autoarray<string>* macrosublabels;
287
288 // randomdude999: ns is still the string to prefix to all labels, it's calculated whenever namespace_list is changed
289 string ns;
290 static string ns_backup;
291 autoarray<string> namespace_list;
292
293 autoarray<string> includeonce;
294
295 autoarray<freespace_data> freespaces;
296
297 // id of the next unused freespace.
298 static int freespaceidnext;
299 // id of the current freespace, or 0 if not in freespace.
300 int freespaceid;
301 // start address of the current freespace, used for computing the length of the
302 // current freespace.
303 static int freespacestart;
304 static freespace_data default_freespace_settings;
305
306 1204 bool confirmname(const char * name)
307 {
308
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 599 times.
✓ Branch 2 taken 605 times.
1204 if (!name[0]) return false;
309
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 599 times.
✓ Branch 2 taken 605 times.
1204 if (is_digit(name[0])) return false;
310
4/4
✓ Branch 0 taken 5988 times.
✓ Branch 1 taken 599 times.
✓ Branch 2 taken 6006 times.
✓ Branch 3 taken 605 times.
13198 for (int i=0;name[i];i++)
311 {
312
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5988 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6006 times.
11994 if (!is_ualnum(name[i])) return false;
313 }
314 1204 return true;
315 }
316
317 53070 string posneglabelname(const char ** input, bool define)
318 {
319 53070 const char* label = *input;
320
321 53070 string output;
322
323 53070 int depth = 0;
324 53070 bool ismacro = false;
325
326
3/3
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 26331 times.
✓ Branch 2 taken 26716 times.
53070 if (label[0] == '?')
327 {
328 46 ismacro = true;
329 46 label++;
330 }
331
6/6
✓ Branch 0 taken 26306 times.
✓ Branch 1 taken 26733 times.
✓ Branch 2 taken 97 times.
✓ Branch 3 taken 26240 times.
✓ Branch 4 taken 72 times.
✓ Branch 5 taken 26636 times.
53070 if (label[0] == '-' || label[0] == '+')
332 {
333 194 char first = label[0];
334
6/6
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 62 times.
✓ Branch 2 taken 223 times.
✓ Branch 3 taken 103 times.
✓ Branch 4 taken 103 times.
✓ Branch 5 taken 29 times.
388 for (depth = 0; label[0] && label[0] == first; depth++) label++;
335
336
2/2
✓ Branch 0 taken 178 times.
✓ Branch 1 taken 16 times.
194 if (!ismacro)
337 {
338
2/2
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 48 times.
178 if (first == '+')
339 {
340 130 *input = label;
341
12/22
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 130 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 62 times.
✓ Branch 5 taken 68 times.
✓ Branch 6 taken 62 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 62 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 130 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 62 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 68 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 68 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 68 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 68 times.
✗ Branch 21 not taken.
130 output = STR":pos_" + dec(depth) + "_" + dec(poslabels[depth]);
342
3/4
✓ Branch 0 taken 105 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 105 times.
✗ Branch 3 not taken.
130 if (define) poslabels[depth]++;
343 }
344 else
345 {
346 48 *input = label;
347
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
48 if (define) neglabels[depth]++;
348
12/22
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 21 times.
✓ Branch 5 taken 27 times.
✓ Branch 6 taken 21 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 21 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 48 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 21 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 27 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 27 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 27 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 27 times.
✗ Branch 21 not taken.
48 output = STR":neg_" + dec(depth) + "_" + dec(neglabels[depth]);
349 }
350 }
351 else
352 {
353
3/6
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 16 times.
16 if (macrorecursion == 0 || macroposlabels == nullptr || macroneglabels == nullptr)
354 {
355 if (!macrorecursion) throw_err_block(0, err_macro_label_outside_of_macro);
356 }
357 else
358 {
359
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 if (first == '+')
360 {
361 8 *input = label;
362
16/32
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 4 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 8 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 4 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 4 times.
✓ Branch 19 taken 4 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 4 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 4 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 4 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 4 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 4 times.
✗ Branch 31 not taken.
8 output = STR":macro_" + dec(calledmacros) + "_pos_" + dec(depth) + "_" + dec((*macroposlabels)[depth]);
363
4/5
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
8 if (define) (*macroposlabels)[depth]++;
364 }
365 else
366 {
367 8 *input = label;
368
4/5
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
8 if (define) (*macroneglabels)[depth]++;
369
16/32
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 4 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 8 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 4 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 4 times.
✓ Branch 19 taken 4 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 4 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 4 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 4 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 4 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 4 times.
✗ Branch 31 not taken.
8 output = STR":macro_" + dec(calledmacros) + "_neg_" + dec(depth) + "_" + dec((*macroneglabels)[depth]);
370 }
371 }
372 }
373 }
374
375 53070 return output;
376 }
377
378 2343 string labelname(const char ** rawname, bool define, bool is_addlabel)
379 {
380 #define deref_rawname (*rawname)
381 2343 autoarray<string>* sublabellist = &sublabels;
382
383 2343 bool ismacro = (deref_rawname[0] == '?');
384 2343 bool issublabel = false;
385
386
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2319 times.
2343 if (ismacro)
387 {
388 24 deref_rawname++;
389 24 sublabellist = macrosublabels;
390 }
391
392 2343 string name;
393 2343 int i=-1;
394
395
2/7
✗ Branch 0 not taken.
✓ Branch 1 taken 1162 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1181 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
2343 if (is_digit(*deref_rawname)) throw_err_block(2, err_invalid_label_name);
396
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1162 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1181 times.
2343 if (*deref_rawname ==':')
397 {
398 deref_rawname++;
399 name=":";
400 }
401
7/8
✓ Branch 0 taken 1045 times.
✓ Branch 1 taken 1298 times.
✓ Branch 2 taken 2097 times.
✓ Branch 3 taken 129 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1064 times.
✓ Branch 6 taken 1052 times.
✓ Branch 7 taken 12 times.
2343 else if (!in_struct && !in_sub_struct)
402 {
403
4/4
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 1033 times.
✓ Branch 2 taken 53 times.
✓ Branch 3 taken 1052 times.
2185 for (i=0;(*deref_rawname =='.');i++) deref_rawname++;
404
2/7
✗ Branch 0 not taken.
✓ Branch 1 taken 1033 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1052 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
2085 if (!is_ualnum(*deref_rawname)) throw_err_block(2, err_invalid_label_name);
405
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 1991 times.
2085 if (i)
406 {
407
7/14
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
✓ Branch 3 taken 50 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 44 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 44 times.
✓ Branch 8 taken 50 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 50 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
94 if (!sublabellist || !(*sublabellist)[i - 1]) throw_err_block(2, err_label_missing_parent);
408
7/12
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 94 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 44 times.
✓ Branch 5 taken 50 times.
✓ Branch 6 taken 44 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 50 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 50 times.
✗ Branch 11 not taken.
94 name+=STR(*sublabellist)[i-1]+"_";
409 94 issublabel = true;
410 }
411 }
412
413
4/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2319 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 8 times.
2343 if (ismacro && !issublabel)
414 {
415 // RPG Hacker: Don't add the prefix for sublabels, because they already inherit it from
416 // their parents' names.
417
4/6
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
16 if (!macrorecursion || macrosublabels == nullptr) throw_err_block(2, err_macro_label_outside_of_macro);
418
7/14
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 10 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
10 name = STR":macro_" + dec(calledmacros) + "_" + name;
419 }
420
421
422
7/8
✓ Branch 0 taken 1042 times.
✓ Branch 1 taken 1295 times.
✓ Branch 2 taken 1073 times.
✓ Branch 3 taken 1147 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1061 times.
✓ Branch 6 taken 12 times.
✓ Branch 7 taken 1049 times.
2337 if (in_struct || in_sub_struct)
423 {
424
7/9
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 114 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 114 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
258 if(is_addlabel && *deref_rawname != '.') throw_err_block(2, err_invalid_label_name); //probably should be a better error. TODO!!!
425
4/4
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 120 times.
✓ Branch 3 taken 3 times.
246 if(*deref_rawname == '.') {
426 240 deref_rawname++;
427
4/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 228 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 108 times.
240 if(in_sub_struct)
428 {
429
4/7
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
24 name += struct_parent + ".";
430 }
431
1/2
✓ Branch 0 taken 240 times.
✗ Branch 1 not taken.
240 name += struct_name;
432
1/2
✓ Branch 0 taken 240 times.
✗ Branch 1 not taken.
240 name += '.';
433 }
434 }
435
436
2/7
✗ Branch 0 not taken.
✓ Branch 1 taken 1153 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1172 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
2325 if (!is_ualnum(*deref_rawname)) throw_err_block(2, err_invalid_label_name);
437
438
10/10
✓ Branch 0 taken 1249 times.
✓ Branch 1 taken 7628 times.
✓ Branch 2 taken 1364 times.
✓ Branch 3 taken 8856 times.
✓ Branch 4 taken 7724 times.
✓ Branch 5 taken 1153 times.
✓ Branch 6 taken 96 times.
✓ Branch 7 taken 1172 times.
✓ Branch 8 taken 7799 times.
✓ Branch 9 taken 1172 times.
17848 while (is_ualnum(*deref_rawname) || *deref_rawname == '.')
439 {
440
2/4
✓ Branch 0 taken 7724 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7799 times.
✗ Branch 3 not taken.
15523 name+=*(deref_rawname++);
441 }
442
443
4/4
✓ Branch 0 taken 963 times.
✓ Branch 1 taken 1362 times.
✓ Branch 2 taken 735 times.
✓ Branch 3 taken 228 times.
2325 if (define && i>=0)
444 {
445 735 (*sublabellist).reset(i);
446
4/7
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 375 times.
✓ Branch 2 taken 360 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 375 times.
✗ Branch 6 not taken.
735 (*sublabellist)[i]=name;
447 }
448 2325 return name;
449 #undef deref_rawname
450 18 }
451
452 192 static inline bool labelvalcore(const char ** rawname, snes_label * rval, bool define, bool shouldthrow)
453 {
454
2/3
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 97 times.
✗ Branch 2 not taken.
192 string name=labelname(rawname, define);
455
11/30
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 190 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 95 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 97 times.
✓ Branch 12 taken 95 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✓ Branch 15 taken 95 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 97 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
192 if (ns && labels.exists(ns+name)) {*rval = labels.find(ns+name);}
456
4/6
✓ Branch 0 taken 192 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 169 times.
✓ Branch 3 taken 23 times.
✓ Branch 4 taken 169 times.
✗ Branch 5 not taken.
192 else if (labels.exists(name)) {*rval = labels.find(name);}
457 else
458 {
459
3/4
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 22 times.
23 if (shouldthrow && pass)
460 {
461
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 throw_err_block(2, err_label_not_found, name.data());
462 }
463 22 rval->pos = (unsigned int)-1;
464 22 rval->freespace_id = 0;
465 22 rval->is_static = false;
466 22 return false;
467 }
468 169 return true;
469 192 }
470
471 170 snes_label labelval(const char ** rawname, bool define)
472 {
473 170 snes_label rval;
474
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 1 times.
170 labelvalcore(rawname, &rval, define, true);
475 169 return rval;
476 }
477
478 22 snes_label labelval(string name, bool define)
479 {
480 22 const char * rawname=name;
481 22 snes_label rval;
482
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 labelvalcore(&rawname, &rval, define, true);
483 44 return rval;
484 }
485
486 bool labelval(const char ** rawname, snes_label * rval, bool define)
487 {
488 return labelvalcore(rawname, rval, define, false);
489 }
490
491 bool labelval(string name, snes_label * rval, bool define)
492 {
493 const char * str=name;
494 return labelvalcore(&str, rval, define, false);
495 }
496
497 1324 static void setlabel(string name, int loc=-1, bool is_static=false)
498 {
499 1324 int lbl_fs_id = 0;
500
2/2
✓ Branch 0 taken 1083 times.
✓ Branch 1 taken 241 times.
1324 if (loc==-1)
501 {
502
1/2
✓ Branch 0 taken 1083 times.
✗ Branch 1 not taken.
1083 verifysnespos();
503 1083 loc = snespos;
504 // if base is not active:
505
2/2
✓ Branch 0 taken 831 times.
✓ Branch 1 taken 252 times.
1083 if(snespos == realsnespos) lbl_fs_id = freespaceid;
506 // if base is active, always treat the label as freespace 0, i.e. not freespace.
507 }
508
509 1324 snes_label label_data;
510 1324 label_data.pos = (unsigned int)loc;
511 1324 label_data.is_static = is_static;
512 1324 label_data.freespace_id = lbl_fs_id;
513
514 unsigned int labelpos;
515
2/2
✓ Branch 0 taken 440 times.
✓ Branch 1 taken 884 times.
1324 if (pass==0)
516 {
517
3/4
✓ Branch 0 taken 440 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 438 times.
440 if (labels.exists(name))
518 {
519 2 movinglabelspossible=true;
520
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 throw_err_block(0, err_label_redefined, name.data());
521 }
522
1/2
✓ Branch 0 taken 438 times.
✗ Branch 1 not taken.
438 labels.create(name) = label_data;
523 }
524
2/2
✓ Branch 0 taken 442 times.
✓ Branch 1 taken 442 times.
884 else if (pass==1)
525 {
526
1/2
✓ Branch 0 taken 442 times.
✗ Branch 1 not taken.
442 labels.create(name) = label_data;
527 }
528
1/2
✓ Branch 0 taken 442 times.
✗ Branch 1 not taken.
442 else if (pass==2)
529 {
530 //all label locations are known at this point, add a sanity check
531
2/6
✓ Branch 0 taken 442 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 442 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
442 if (!labels.exists(name)) throw_err_block(2, err_internal_error, "label created on 3rd pass");
532
1/2
✓ Branch 0 taken 442 times.
✗ Branch 1 not taken.
442 labelpos = labels.find(name).pos;
533
5/6
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 436 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
442 if ((int)labelpos != loc && !movinglabelspossible)
534 {
535
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6 if((unsigned int)loc>>16 != labelpos>>16) throw_err_block(2, err_label_ambiguous, name.data());
536
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
6 else if(labelpos == (dp_base + 0xFFu)) throw_err_block(2, err_label_ambiguous, name.data());
537
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 else if(errored) return;
538 else throw_err_block(2, err_internal_error, "moving label");
539 }
540 }
541 }
542
543 table thetable;
544 static autoarray<table> tablestack;
545
546 841 static void cleartable()
547 {
548
4/7
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 467 times.
✓ Branch 2 taken 374 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 467 times.
✗ Branch 6 not taken.
841 thetable = table();
549 841 }
550
551 struct pushable {
552 int arch;
553 int snespos;
554 int snesstart;
555 int snesposreal;
556 int snesstartreal;
557 int freeid;
558 int freest;
559 int arch1;
560 int arch2;
561 int arch3;
562 int arch4;
563 };
564 static autoarray<pushable> pushpc;
565 static int pushpcnum;
566
567 static autoarray<int> basestack;
568 static int basestacknum;
569
570 struct ns_pushable {
571 string ns;
572 autoarray<string> namespace_list;
573 bool nested_namespaces;
574 };
575
576 static autoarray<ns_pushable> pushns;
577 static int pushnsnum;
578
579
580 static unsigned char fillbyte[12];
581 static unsigned char padbyte[12];
582
583 static bool nested_namespaces = false;
584
585 48392 void checkbankcross()
586 {
587
4/4
✓ Branch 0 taken 4641 times.
✓ Branch 1 taken 43751 times.
✓ Branch 2 taken 4713 times.
✓ Branch 3 taken 19636 times.
48392 if (!snespos_valid) return;
588
4/4
✓ Branch 0 taken 189 times.
✓ Branch 1 taken 38849 times.
✓ Branch 2 taken 189 times.
✓ Branch 3 taken 19447 times.
39038 if (disable_bank_cross_errors) return;
589
4/4
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 38514 times.
✓ Branch 2 taken 146 times.
✓ Branch 3 taken 19301 times.
38660 unsigned int mask = 0x7FFF0000 | (check_half_banks_crossed ? 0x8000 : 0);
590
4/4
✓ Branch 0 taken 588 times.
✓ Branch 1 taken 38072 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 584 times.
38660 if (((snespos^startpos) & mask) && (((snespos - 1) ^ startpos) & mask))
591 {
592 4 throw_err_fatal(pass, err_bank_border_crossed, snespos);
593 }
594 // don't verify realsnespos when using norom. this allows making custom mappers where the file layout doesn't follow bank borders
595
7/8
✓ Branch 0 taken 19070 times.
✓ Branch 1 taken 19586 times.
✓ Branch 2 taken 19551 times.
✓ Branch 3 taken 18964 times.
✓ Branch 4 taken 298 times.
✓ Branch 5 taken 19253 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 298 times.
38656 else if (mapper != norom && ((realsnespos^realstartpos) & mask) && (((realsnespos - 1) ^ realstartpos) & mask))
596 {
597 throw_err_fatal(pass, err_bank_border_crossed, realsnespos);
598 }
599 }
600
601 3297 static void freespaceend()
602 {
603
2/2
✓ Branch 0 taken 1572 times.
✓ Branch 1 taken 1725 times.
3297 if (freespaceid > 0)
604 {
605 1572 freespaces[freespaceid].len = realsnespos-freespacestart;
606 1572 snespos=(int)0xFFFFFFFF;
607 1572 snespos_valid = false;
608 }
609 3297 freespaceid = 0;
610 3297 }
611
612 2532 static void adddefine(const string & key, string & value)
613 {
614
2/4
✓ Branch 0 taken 1113 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1419 times.
✗ Branch 3 not taken.
2532 if (!defines.exists(key)) defines.create(key) = value;
615 2532 }
616
617 835 void initstuff()
618 {
619
2/2
✓ Branch 0 taken 285 times.
✓ Branch 1 taken 550 times.
835 if (pass==0)
620 {
621 285 freespaces.reset();
622 285 movinglabelspossible = false;
623 285 found_rats_tags_initialized = false;
624 285 found_rats_tags.clear();
625 }
626 835 arch=arch_65816;
627 835 mapper=lorom;
628 835 mapper_set = false;
629 835 calledmacros = 0;
630 835 reallycalledmacros = 0;
631 835 macrorecursion = 0;
632 835 defines.reset();
633 835 builtindefines.each(adddefine);
634 835 clidefines.each(adddefine);
635 835 ns="";
636 835 namespace_list.reset();
637 835 sublabels.reset();
638 835 poslabels.reset();
639 835 neglabels.reset();
640 835 macroposlabels = nullptr;
641 835 macroneglabels = nullptr;
642 835 macrosublabels = nullptr;
643 835 cleartable();
644 835 pushpc.reset();
645 835 pushpcnum=0;
646 835 pushns.reset();
647 835 pushnsnum = 0;
648 835 bytes=0;
649 835 freespaceuse=0;
650
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 464 times.
835 memset(fillbyte, 0, sizeof(fillbyte));
651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 464 times.
835 memset(padbyte, 0, sizeof(padbyte));
652 835 snespos_valid = false;
653 835 snespos=(int)0xFFFFFFFF;
654 835 realsnespos= (int)0xFFFFFFFF;
655 835 startpos= (int)0xFFFFFFFF;
656 835 realstartpos= (int)0xFFFFFFFF;
657 835 freespaceidnext=1;
658 835 freespaceid=0;
659 835 freespacebyte=0x00;
660 835 incsrcdepth = 0;
661
662 835 optimizeforbank = -1;
663 835 optimize_dp = optimize_dp_flag::ALWAYS;
664 835 dp_base = 0;
665 835 optimize_address = optimize_address_flag::MIRRORS;
666
667 835 in_struct = false;
668 835 in_sub_struct = false;
669 835 in_spcblock = false;
670
671 835 disable_bank_cross_errors = false;
672 835 check_half_banks_crossed = false;
673 835 nested_namespaces = false;
674
675 835 includeonce.reset();
676
677 extern AddressToLineMapping addressToLineMapping;
678 835 addressToLineMapping.reset();
679
680 835 push_warnings(false);
681
682 835 initmathcore();
683
684 1299 default_freespace_settings = {};
685 835 default_freespace_settings.bank = -3;
686 835 default_freespace_settings.search_start = -1;
687 835 default_freespace_settings.write_rats = true;
688 // rest are initialized to false/0/empty string
689
690 835 callstack.clear();
691 #if defined(_WIN32) || !defined(NO_USE_THREADS)
692 835 init_stack_use_check();
693 #endif
694 835 }
695
696 1572 static void parse_freespace_arguments(freespace_data& thisfs, string& arguments) {
697
3/3
✓ Branch 0 taken 105 times.
✓ Branch 1 taken 786 times.
✓ Branch 2 taken 681 times.
1572 if(arguments == "") return;
698
2/4
✓ Branch 0 taken 681 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 681 times.
✗ Branch 3 not taken.
1362 autoptr<char**> pars=qpsplit(arguments.temp_raw(), ',');
699
700
4/4
✓ Branch 0 taken 690 times.
✓ Branch 1 taken 681 times.
✓ Branch 2 taken 690 times.
✓ Branch 3 taken 681 times.
2742 for (int i=0;pars[i];i++)
701 {
702
3/6
✓ Branch 0 taken 690 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1380 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 690 times.
1380 if (!stricmp(pars[i], "ram")) { thisfs.bank = -2; }
703
5/6
✓ Branch 0 taken 690 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1377 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 687 times.
1380 else if (!stricmp(pars[i], "noram")) { thisfs.bank = -1; }
704
5/6
✓ Branch 0 taken 687 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1368 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 681 times.
1374 else if (!stricmp(pars[i], "static")) { thisfs.is_static = true; }
705
3/6
✓ Branch 0 taken 681 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1362 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 681 times.
1362 else if (!stricmp(pars[i], "nostatic")) { thisfs.is_static = false; }
706
5/6
✓ Branch 0 taken 681 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1356 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 675 times.
1362 else if (!stricmp(pars[i], "align")) { thisfs.flag_align = true; }
707
3/6
✓ Branch 0 taken 675 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1350 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 675 times.
1350 else if (!stricmp(pars[i], "noalign")) { thisfs.flag_align = false; }
708
5/6
✓ Branch 0 taken 675 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 636 times.
✓ Branch 3 taken 714 times.
✓ Branch 4 taken 636 times.
✓ Branch 5 taken 39 times.
1350 else if (!stricmp(pars[i], "cleaned")) { thisfs.flag_cleaned = true; }
709
3/6
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 78 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 39 times.
78 else if (!stricmp(pars[i], "nocleaned")) { thisfs.flag_cleaned = false; }
710
3/6
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 78 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 39 times.
78 else if (!stricmp(pars[i], "rats")) { thisfs.write_rats = true; }
711
3/6
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 78 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 39 times.
78 else if (!stricmp(pars[i], "norats")) { thisfs.write_rats = false; }
712
3/6
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 78 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 39 times.
78 else if (!stricmp(pars[i], "bankcross")) { thisfs.allow_bankcross = true; }
713
3/6
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 78 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 39 times.
78 else if (!stricmp(pars[i], "nobankcross")) { thisfs.allow_bankcross = false; }
714
4/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 24 times.
78 else if (stribegin(pars[i], "bank="))
715 {
716
6/11
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 15 times.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 15 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 15 times.
✗ Branch 10 not taken.
30 thisfs.bank = parse_math_expr(pars[i] + 5)->evaluate_static().get_integer();
717 }
718
4/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 12 times.
48 else if (stribegin(pars[i], "start="))
719 {
720
6/11
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 12 times.
✗ Branch 10 not taken.
24 thisfs.search_start = parse_math_expr(pars[i] + 6)->evaluate_static().get_integer();
721 }
722
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
24 else if (stribegin(pars[i], "pin="))
723 {
724 // TODO: should we handle posneg labels here too?
725
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
24 string pin_to = pars[i] + 4;
726 24 const char* pin_to_c = pin_to.data();
727
2/3
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
24 thisfs.pin_target = labelname(&pin_to_c);
728
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
24 if(*pin_to_c) throw_err_block(0, err_invalid_label_name);
729 // this is to throw an "undefined label" error with the proper callstack
730
6/8
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
24 if(pass) labelval(pin_to);
731
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
24 thisfs.pin_target_ns = ns;
732 24 }
733 else throw_err_block(0, err_invalid_freespace_request);
734 }
735 1362 }
736
737 530 static int get_freespace_pin_target(int target_id) {
738 // union-find algorithm
739
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 265 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 265 times.
534 while(freespaces[target_id].pin_target_id != target_id) {
740 // i love programming
741 6 freespaces[target_id].pin_target_id =
742 4 freespaces[freespaces[target_id].pin_target_id].pin_target_id;
743 4 target_id = freespaces[target_id].pin_target_id;
744 }
745 530 return target_id;
746 }
747
748 275 static void resolve_pinned_freespaces() {
749
2/2
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 275 times.
797 for(int i = 1; i < freespaces.count; i++)
750 // default to everyone being in a separate component
751 522 freespaces[i].pin_target_id = i;
752
2/2
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 275 times.
797 for(int i = 1; i < freespaces.count; i++) {
753
1/2
✓ Branch 0 taken 522 times.
✗ Branch 1 not taken.
522 freespace_data& fs = freespaces[i];
754
4/4
✓ Branch 0 taken 257 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 257 times.
✓ Branch 3 taken 4 times.
522 if(fs.pin_target == "") continue;
755 8 snes_label value;
756
7/29
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 4 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 4 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 4 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 4 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
8 if(fs.pin_target_ns && labels.exists(fs.pin_target_ns + fs.pin_target))
757 value = labels.find(fs.pin_target_ns + fs.pin_target);
758
4/7
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
8 else if(labels.exists(fs.pin_target))
759
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
8 value = labels.find(fs.pin_target);
760 else continue; // the error for this is thrown in the freespace command during pass 2
761
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 fs.pin_target_id = get_freespace_pin_target(value.freespace_id);
762 8 fs.len = 0;
763 }
764 275 }
765
766 275 static void allocate_freespaces() {
767 // compute real size of all pinned freespace blocks
768
2/2
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 275 times.
797 for(int i = 1; i < freespaces.count; i++) {
769 522 freespace_data& fs = freespaces[i];
770 // just in case the pin target changed again or something
771 522 fs.pin_target_id = get_freespace_pin_target(fs.pin_target_id);
772 522 freespace_data& target = freespaces[fs.pin_target_id];
773 522 target.total_len += fs.len;
774 522 target.search_start = std::max(fs.search_start, target.search_start);
775 }
776
777
2/2
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 275 times.
797 for(int i = 1; i < freespaces.count; i++) {
778 522 freespace_data& fs = freespaces[i];
779
7/7
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 259 times.
✓ Branch 2 taken 262 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 259 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
522 if(fs.is_static && fs.orgpos > 0) {
780 2 fs.pos = fs.orgpos;
781 2 continue;
782 }
783 // if this freespace is pinned to another one, set it later
784
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 257 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 257 times.
520 if(fs.pin_target_id != i) continue;
785 // TODO: possibly fancier align
786
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 257 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 257 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 257 times.
514 fs.pos = getsnesfreespace(fs.total_len, fs.bank, true, !fs.allow_bankcross, fs.flag_align, fs.write_rats, fs.search_start);
787 514 fs.used_len = fs.len;
788 }
789 // set pos for all pinned freespaces
790
2/2
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 275 times.
797 for(int i = 1; i < freespaces.count; i++) {
791 522 freespace_data& fs = freespaces[i];
792
4/4
✓ Branch 0 taken 258 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 258 times.
✓ Branch 3 taken 3 times.
522 if(fs.pin_target_id == i) continue;
793 6 freespace_data& tgt = freespaces[fs.pin_target_id];
794 6 fs.pos = tgt.pos + tgt.used_len;
795 6 tgt.used_len += fs.len;
796 }
797
798 // relocate all labels that were in freespace to point them to their real location
799 275 labels.each([](const char * key, snes_label & val) {
800
4/4
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 171 times.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 179 times.
440 if(val.freespace_id != 0) {
801 90 val.pos += freespaces[val.freespace_id].pos;
802 }
803 440 });
804 275 }
805
806 825 void finishpass()
807 {
808 825 verify_warnings();
809 825 pull_warnings(false);
810
811
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 825 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 459 times.
825 if(in_spcblock) throw_err_block(0, err_missing_endspcblock);
812
6/8
✓ Branch 0 taken 366 times.
✓ Branch 1 taken 459 times.
✓ Branch 2 taken 459 times.
✓ Branch 3 taken 366 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 459 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 459 times.
825 if (in_struct || in_sub_struct) throw_err_null(0, err_struct_without_endstruct);
813
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 825 times.
825 else if (pushpcnum) throw_err_null(0, err_pushpc_without_pullpc);
814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 825 times.
825 else if (pushnsnum) throw_err_null(0, err_pushns_without_pullns);
815 825 freespaceend();
816
817 825 deinitmathcore();
818
2/2
✓ Branch 0 taken 275 times.
✓ Branch 1 taken 550 times.
825 if(pass == 0) {
819 275 resolve_pinned_freespaces();
820
2/2
✓ Branch 0 taken 275 times.
✓ Branch 1 taken 275 times.
550 } else if(pass == 1) {
821 275 allocate_freespaces();
822 275 handle_cleared_rats_tags();
823 }
824 #if defined(_WIN32) || !defined(NO_USE_THREADS)
825 825 deinit_stack_use_check();
826 #endif
827 825 }
828
829 32483 static bool addlabel(const char * label, int pos=-1, bool global_label = false)
830 {
831
4/6
✓ Branch 0 taken 16111 times.
✓ Branch 1 taken 16372 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16111 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 16372 times.
32483 if (!label[0] || label[0]==':') return false;//colons are reserved for special labels
832
833 32483 const char* posneglabel = label;
834
2/3
✓ Branch 0 taken 16111 times.
✓ Branch 1 taken 16372 times.
✗ Branch 2 not taken.
32483 string posnegname = posneglabelname(&posneglabel, true);
835
836
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 32357 times.
32483 if (posnegname.length() > 0)
837 {
838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
126 if (global_label) return false;
839
5/9
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 60 times.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
126 if (*posneglabel != '\0' && *posneglabel != ':') throw_err_block(0, err_broken_label_definition);
840
4/6
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 66 times.
✗ Branch 5 not taken.
126 setlabel(posnegname, pos);
841 126 return true;
842 }
843
11/13
✓ Branch 0 taken 15580 times.
✓ Branch 1 taken 16777 times.
✓ Branch 2 taken 15550 times.
✓ Branch 3 taken 30 times.
✓ Branch 4 taken 31370 times.
✓ Branch 5 taken 486 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 31337 times.
✓ Branch 8 taken 33 times.
✓ Branch 9 taken 15787 times.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 15787 times.
32357 if (label[strlen(label)-1]==':' || label[0]=='.' || label[0]=='?' || label[0] == '#')
844 {
845
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 498 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 513 times.
1023 if (!label[1]) return false;
846
10/12
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 969 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 21 times.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 39 times.
✓ Branch 8 taken 21 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✓ Branch 11 taken 18 times.
1011 if(global_label && (in_struct || in_sub_struct || label[0]=='?')) return false;
847
848 1005 bool define = true;
849
850
3/3
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 495 times.
✓ Branch 2 taken 498 times.
1005 if (label[0] == '#')
851 {
852 24 define = false;
853 24 label++;
854 }
855
856 // RPG Hacker: Also checking label[1] now, since it might be a macro sublabel.
857 // Also, apparently this here doesn't account for main labels. I guess because
858 // we don't even get here in the first place if they don't include a colon?
859
13/15
✓ Branch 0 taken 342 times.
✓ Branch 1 taken 504 times.
✓ Branch 2 taken 498 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 333 times.
✓ Branch 5 taken 354 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 333 times.
✓ Branch 8 taken 348 times.
✓ Branch 9 taken 342 times.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 342 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 342 times.
1005 bool requirecolon = (label[0] != '.' && label[1] != '.') && (in_struct || in_sub_struct);
860
3/3
✓ Branch 0 taken 486 times.
✓ Branch 1 taken 510 times.
✓ Branch 2 taken 9 times.
1005 string name=labelname(&label, define, true);
861
3/3
✓ Branch 0 taken 453 times.
✓ Branch 1 taken 498 times.
✓ Branch 2 taken 36 times.
987 if (label[0]==':') label++;
862
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
69 else if (requirecolon) throw_err_block(0, err_broken_label_definition);
863
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 63 times.
69 else if (global_label) return false;
864
4/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 483 times.
✓ Branch 2 taken 498 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
981 if (label[0]) throw_err_block(0, err_broken_label_definition);
865
8/9
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 846 times.
✓ Branch 2 taken 99 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 99 times.
✓ Branch 5 taken 858 times.
✓ Branch 6 taken 48 times.
✓ Branch 7 taken 51 times.
✗ Branch 8 not taken.
957 if (ns && !global_label) name=ns+name;
866
15/16
✓ Branch 0 taken 372 times.
✓ Branch 1 taken 585 times.
✓ Branch 2 taken 399 times.
✓ Branch 3 taken 459 times.
✓ Branch 4 taken 81 times.
✓ Branch 5 taken 417 times.
✓ Branch 6 taken 483 times.
✓ Branch 7 taken 375 times.
✓ Branch 8 taken 469 times.
✓ Branch 9 taken 113 times.
✓ Branch 10 taken 81 times.
✓ Branch 11 taken 30 times.
✓ Branch 12 taken 486 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 484 times.
✓ Branch 15 taken 2 times.
961 setlabel(name, pos, ((in_struct || in_sub_struct) && static_struct));
867 953 return true;
868 987 }
869 31334 return false;
870 32483 }
871
872 15580 static void add_addr_to_line(int pos)
873 {
874
2/2
✓ Branch 0 taken 5498 times.
✓ Branch 1 taken 10082 times.
15580 if (pass == 2)
875 5498 addressToLineMapping.includeMapping(get_current_file_name(), get_current_line() + 1, pos);
876 15580 }
877
878 static autoarray<bool> elsestatus;
879 int numtrue=0;//if 1 -> increase both
880 int numif = 0; //if 0 or inside if 0 -> increase only numif
881
882 autoarray<whiletracker> whilestatus;
883
884
885 112 static void push_pc()
886 {
887 112 pushpc[pushpcnum].arch=arch;
888 112 pushpc[pushpcnum].snespos=snespos;
889 112 pushpc[pushpcnum].snesstart=startpos;
890 112 pushpc[pushpcnum].snesposreal=realsnespos;
891 112 pushpc[pushpcnum].snesstartreal=realstartpos;
892 112 pushpc[pushpcnum].freeid=freespaceid;
893 112 pushpc[pushpcnum].freest=freespacestart;
894 112 pushpcnum++;
895 112 }
896
897 112 static void pop_pc()
898 {
899 112 pushpcnum--;
900 112 snespos=pushpc[pushpcnum].snespos;
901 112 startpos=pushpc[pushpcnum].snesstart;
902 112 realsnespos=pushpc[pushpcnum].snesposreal;
903 112 realstartpos=pushpc[pushpcnum].snesstartreal;
904 112 freespaceid=pushpc[pushpcnum].freeid;
905 112 freespacestart=pushpc[pushpcnum].freest;
906 112 }
907
908
909 372 static string handle_print(const char* input)
910 {
911 // evaluating this math can be unsafe in pass 0
912
3/4
✓ Branch 0 taken 244 times.
✓ Branch 1 taken 128 times.
✓ Branch 2 taken 244 times.
✗ Branch 3 not taken.
372 if(pass != 2) return "";
913 128 string out;
914
2/3
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
128 string buf = input;
915
2/3
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
128 autoptr<char**> pars = qpsplit(buf.raw(), ',');
916
1/2
✓ Branch 0 taken 128 times.
✗ Branch 1 not taken.
128 verify_paren(pars);
917
4/4
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 108 times.
✓ Branch 3 taken 62 times.
329 for (int i = 0; pars[i]; i++)
918 {
919 if (0);
920 // leaving these here is kinda hacky, but whatever...
921
8/12
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 207 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 106 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
209 else if (!stricmp(pars[i], "bytes")) out += dec(bytes);
922
8/12
✓ Branch 0 taken 99 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 204 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 105 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
205 else if (!stricmp(pars[i], "freespaceuse")) out += dec(freespaceuse);
923
3/12
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 203 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 105 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
203 else if (!stricmp(pars[i], "pc")) out += hex((unsigned int)(snespos & 0xFFFFFF), 6);
924 else {
925
5/6
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 199 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 101 times.
✓ Branch 5 taken 4 times.
426 math_val value = parse_math_expr(pars[i])->evaluate();
926
2/4
✓ Branch 0 taken 195 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195 times.
✗ Branch 3 not taken.
195 out += value.get_str();
927 195 }
928 }
929 120 return out;
930 347 }
931
932 114 void handle_autoclean(string& arg, int checkbyte, int write_pos)
933 {
934
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
114 if(freespaceid > 0) throw_err_block(0, err_autoclean_in_freespace);
935
936 114 const char* labeltest = arg.data();
937
1/2
✓ Branch 0 taken 114 times.
✗ Branch 1 not taken.
114 snes_label lblval = labelval(&labeltest);
938
2/7
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
✓ Branch 2 taken 57 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
114 if (*labeltest) throw_err_block(0, err_label_not_found, arg.data());
939 114 int num = lblval.pos;
940
1/2
✓ Branch 0 taken 114 times.
✗ Branch 1 not taken.
114 auto& targetfs = freespaces[lblval.freespace_id];
941
942
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 60 times.
114 if (pass == 1) {
943 54 targetfs.leaked = false;
944
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 6 times.
54 int orig_pos = read3(checkbyte != -1 ? write_pos+1 : write_pos);
945 54 int write_pos_pc = snestopc(write_pos);
946 54 targetfs.orgpos = targetfs.orglen = -1;
947
8/10
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 48 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 11 times.
✓ Branch 7 taken 13 times.
✓ Branch 8 taken 11 times.
✓ Branch 9 taken 13 times.
54 if(write_pos_pc >= 0 && write_pos_pc < romlen_r && (checkbyte == -1 || romdata_r[write_pos_pc] == checkbyte)) {
948
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 int rats_loc = ratsstart(orig_pos);
949
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 6 times.
28 if(rats_loc != -1) {
950 22 targetfs.orgpos = rats_loc + 8;
951 22 targetfs.orglen = read2(rats_loc + 4) + 1;
952
6/7
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
22 if(!targetfs.is_static) removerats(rats_loc + 8, freespacebyte);
953 }
954 }
955
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 6 times.
60 } else if(pass == 2) {
956
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 27 times.
54 if(targetfs.pos < 0) {
957 // this freespace failed to allocate.
958 // ratsstart is obviously not going to find a nonexistent freespace,
959 // and would error too, we don't need 2 errors about the same thing.
960 // especially if one of them is as weird as this one.
961 return;
962 }
963
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 int start = ratsstart(num);
964
2/6
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
54 if(start >= num || start < 0) throw_err_block(2, err_autoclean_label_at_freespace_end);
965 }
966 }
967
968 namespace {
969
970 template<void (*do_write)(unsigned int)>
971 9654 void cmd_write_data(const char* par) {
972 9654 int addrToLinePos = realsnespos & 0xFFFFFF;
973
2/3
✓ Branch 0 taken 2376 times.
✓ Branch 1 taken 2451 times.
✗ Branch 2 not taken.
9654 string line = par;
974
2/3
✓ Branch 0 taken 2376 times.
✓ Branch 1 taken 2451 times.
✗ Branch 2 not taken.
9654 autoptr<char**> pars=qpsplit(line.temp_raw(), ',');
975
1/2
✓ Branch 0 taken 4827 times.
✗ Branch 1 not taken.
9654 verify_paren(pars);
976
977
4/4
✓ Branch 0 taken 2782 times.
✓ Branch 1 taken 2363 times.
✓ Branch 2 taken 2896 times.
✓ Branch 3 taken 2438 times.
20958 for (int i=0;pars[i];i++)
978 {
979
4/4
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 2671 times.
✓ Branch 2 taken 114 times.
✓ Branch 3 taken 2782 times.
11356 if (pars[i][0]=='"') {
980
2/4
✓ Branch 0 taken 111 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 114 times.
✗ Branch 3 not taken.
450 const char * str = safedequote(pars[i]);
981 450 int codepoint = 0u;
982
1/2
✓ Branch 0 taken 225 times.
✗ Branch 1 not taken.
450 str += utf8_val(&codepoint, str);
983
3/4
✓ Branch 0 taken 918 times.
✓ Branch 1 taken 225 times.
✓ Branch 2 taken 918 times.
✗ Branch 3 not taken.
2286 while ( codepoint != 0 && codepoint != -1 )
984 {
985
1/2
✓ Branch 0 taken 918 times.
✗ Branch 1 not taken.
1836 do_write(thetable.get_val(codepoint));
986
1/2
✓ Branch 0 taken 918 times.
✗ Branch 1 not taken.
1836 str += utf8_val(&codepoint, str);
987 }
988
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 225 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
450 if (codepoint == -1) throw_err_block(0, err_invalid_utf8);
989 } else {
990
36/40
✓ Branch 0 taken 880 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 1792 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 875 times.
✓ Branch 5 taken 1783 times.
✓ Branch 6 taken 875 times.
✓ Branch 7 taken 1783 times.
✓ Branch 8 taken 875 times.
✓ Branch 9 taken 2695 times.
✓ Branch 10 taken 5 times.
✓ Branch 11 taken 13 times.
✓ Branch 12 taken 5 times.
✓ Branch 13 taken 920 times.
✓ Branch 14 taken 5 times.
✓ Branch 15 taken 920 times.
✓ Branch 16 taken 1857 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 912 times.
✓ Branch 19 taken 1857 times.
✓ Branch 20 taken 912 times.
✓ Branch 21 taken 1857 times.
✓ Branch 22 taken 912 times.
✓ Branch 23 taken 1857 times.
✓ Branch 24 taken 912 times.
✓ Branch 25 taken 1857 times.
✓ Branch 26 taken 1857 times.
✓ Branch 27 taken 912 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 13 times.
✓ Branch 30 taken 13 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 5 times.
✓ Branch 33 taken 8 times.
✓ Branch 34 taken 5 times.
✓ Branch 35 taken 8 times.
✓ Branch 36 taken 5 times.
✓ Branch 37 taken 8 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 13 times.
20132 do_write((pass==2) ? parse_math_expr(pars[i])->evaluate().get_integer() : 0);
991 }
992 }
993
1/2
✓ Branch 0 taken 4801 times.
✗ Branch 1 not taken.
9602 add_addr_to_line(addrToLinePos);
994 18176 }
995
996 342 void cmd_assert(const char* par) {
997
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
✓ Branch 2 taken 174 times.
342 if(!*par) {
998 throw_err_block(0, err_broken_command, "assert", "Missing condition.");
999 }
1000 // todo optimize after adding some math helpers
1001
1/2
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
342 const char* message_start = strqpchr(par, ',');
1002
1003 342 string cond_str;
1004
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 312 times.
342 if(message_start) {
1005
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 cond_str.assign(par, message_start - par);
1006 30 message_start++; // eat the comma
1007 } else {
1008
1/2
✓ Branch 0 taken 312 times.
✗ Branch 1 not taken.
312 cond_str = par;
1009 }
1010
1011
2/2
✓ Branch 0 taken 228 times.
✓ Branch 1 taken 114 times.
342 if(pass != 2) return;
1012
1013
7/12
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 101 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 43 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 45 times.
✓ Branch 9 taken 13 times.
✓ Branch 10 taken 45 times.
✗ Branch 11 not taken.
306 bool cond = parse_math_expr(cond_str)->evaluate().get_bool();
1014
1015
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 76 times.
88 if(!cond) {
1016
9/15
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 14 not taken.
36 if (message_start) throw_err_block(2, err_assertion_failed, (string(": ") + handle_print(message_start)).data());
1017
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 else throw_err_block(2, err_assertion_failed, ".");
1018 }
1019
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 228 times.
456 }
1020
1021 120 void cmd_undef(const char* par) {
1022
2/3
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
120 string temp = par;
1023
4/6
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 60 times.
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 60 times.
✗ Branch 5 not taken.
120 string def = safedequote(temp.raw());
1024
4/5
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 60 times.
✓ Branch 4 taken 60 times.
120 if (builtindefines.exists(def)) {
1025 throw_err_line(0, err_overriding_builtin_define, def.data());
1026 }
1027
1028
5/5
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 60 times.
✓ Branch 2 taken 57 times.
✓ Branch 3 taken 60 times.
✓ Branch 4 taken 3 times.
120 if (defines.exists(def)) {
1029
2/3
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
114 defines.remove(def);
1030 } else {
1031
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 throw_err_block(0, err_define_not_found, def.data());
1032 }
1033 183 }
1034
1035 21 void cmd_error(const char* par) {
1036
3/3
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 9 times.
21 if(!*par)
1037
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 throw_err_block(0, err_error_command, ".");
1038
2/3
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
15 string out = handle_print(par);
1039
5/11
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 9 times.
✗ Branch 10 not taken.
54 throw_err_block(2, err_error_command, (string(": ") + out).data());
1040 15 }
1041
1042 33 void cmd_warn(const char* par) {
1043
3/3
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 15 times.
33 if(!*par) {
1044
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 throw_warning(0, warn_warn_command, ".");
1045 6 return;
1046 }
1047
2/3
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
27 string out = handle_print(par);
1048
5/11
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 15 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 15 times.
✗ Branch 10 not taken.
27 throw_warning(2, warn_warn_command, (string(": ") + out).data());
1049 27 }
1050
1051 132 void cmd_warnings(char** words, int numwords) {
1052
7/7
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 84 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 24 times.
✓ Branch 4 taken 24 times.
✓ Branch 5 taken 66 times.
✓ Branch 6 taken 54 times.
132 if(numwords == 1 && !stricmpwithlower(words[0], "push")) {
1053 24 push_warnings();
1054
7/7
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 84 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 54 times.
✓ Branch 6 taken 42 times.
108 } else if(numwords == 1 && !stricmpwithlower(words[0], "pull")) {
1055 24 pull_warnings();
1056
6/7
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 42 times.
✓ Branch 4 taken 42 times.
✓ Branch 5 taken 42 times.
✓ Branch 6 taken 33 times.
84 } else if(numwords == 2 && !stricmpwithlower(words[0], "enable")) {
1057 18 asar_warning_id warnid = parse_warning_id_from_string(words[1]);
1058
1059
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
18 if (warnid != warning_id_end) {
1060 12 set_warning_enabled(warnid, true);
1061 } else {
1062 6 throw_warning(0, warn_invalid_warning_id, words[1], "warnings enable");
1063 }
1064
5/7
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 33 times.
✓ Branch 4 taken 33 times.
✓ Branch 5 taken 33 times.
✗ Branch 6 not taken.
66 } else if(numwords == 2 && !stricmpwithlower(words[0], "disable")) {
1065 66 asar_warning_id warnid = parse_warning_id_from_string(words[1]);
1066
1067
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 12 times.
66 if (warnid != warning_id_end) {
1068 54 set_warning_enabled(warnid, false);
1069 } else {
1070 12 throw_warning(0, warn_invalid_warning_id, words[1], "warnings disable");
1071 }
1072 } else {
1073 throw_err_block(0, err_broken_command, "warnings", "Unknown parameter");
1074 }
1075 126 }
1076
1077 42 void cmd_global(const char* par) {
1078
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 30 times.
42 if(!addlabel(par, -1, true)) {
1079 12 throw_err_block(1, err_invalid_global_label, par);
1080 }
1081 30 }
1082
1083 70 void cmd_check(char** words, int numwords) {
1084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
70 if(numwords != 2) throw_err_block(0, err_invalid_check);
1085
1086
3/3
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 32 times.
70 if(!stricmpwithlower(words[0], "title")) {
1087 // RPG Hacker: Removed trimming for now - I think requiring an exact match is probably
1088 // better here (not sure, though, it's worth discussing)
1089
3/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
6 string expected_title = safedequote(words[1]);
1090 // in hirom the rom needs to be an entire bank for it to have a title, other modes only need 0x8000 bytes
1091
7/10
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
6 if (romlen < ((mapper == hirom || mapper == exhirom) ? 0x10000 : 0x8000)) // too short
1092 {
1093 if (!ignoretitleerrors) // title errors shouldn't be ignored
1094 throw_err_block(0, err_rom_too_short, expected_title.data());
1095 else // title errors should be ignored, throw a warning anyways
1096 throw_warning(0, warn_rom_too_short, expected_title.data());
1097 } else {
1098 6 string actual_title;
1099 6 string actual_display_title;
1100
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 6 times.
132 for (int i = 0;i < 21;i++)
1101 {
1102 126 unsigned char c = romdata[snestopc(0x00FFC0 + i)];
1103
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 actual_title += (char)c;
1104 // the replacements are from interface-cli.cpp
1105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
126 if (c == 7) c = 14;
1106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
126 if (c == 8) c = 27;
1107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
126 if (c == 9) c = 26;
1108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
126 if (c == '\r') c = 17;
1109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
126 if (c == '\n') c = 25;
1110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
126 if (c == '\0') c = 155;
1111
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 actual_display_title += (char)c;
1112 }
1113
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
6 if (strncmp(expected_title, actual_title, 21) != 0)
1114 {
1115 if (!ignoretitleerrors) // title errors shouldn't be ignored
1116 throw_err_block(0, err_rom_title_incorrect, expected_title.data(), actual_display_title.data());
1117 else // title errors should be ignored, throw a warning anyways
1118 throw_warning(0, warn_rom_title_incorrect, expected_title.data(), actual_display_title.data());
1119 }
1120 6 }
1121
2/3
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
70 } else if(!stricmpwithlower(words[0], "bankcross")) {
1122
4/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 17 times.
64 if(!stricmpwithlower(words[1], "off")) {
1123 30 disable_bank_cross_errors = true;
1124
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 1 times.
34 } else if(!stricmpwithlower(words[1], "half")) {
1125 32 disable_bank_cross_errors = false;
1126 32 check_half_banks_crossed = true;
1127
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 } else if(!stricmpwithlower(words[1], "full")) {
1128 2 disable_bank_cross_errors = false;
1129 2 check_half_banks_crossed = false;
1130 } else {
1131 throw_err_block(0, err_invalid_check);
1132 }
1133 } else {
1134 throw_err_block(0, err_invalid_check);
1135 }
1136 70 }
1137
1138 36 void cmd_asar(const char* par) {
1139
2/7
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
36 if(!asarverallowed) throw_err_block(0, err_start_of_file);
1140
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 18 times.
51 if(!*par) return;
1141 36 int dots = 0;
1142 36 int dig = 0;
1143
4/4
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 75 times.
✓ Branch 3 taken 18 times.
186 for (int i=0;par[i];i++)
1144 {
1145
4/4
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 54 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 54 times.
150 if (par[i]=='.')
1146 {
1147
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
42 if (!dig) throw_err_block(0, err_invalid_version_number);
1148 42 dig=0;
1149 42 dots++;
1150 }
1151
2/4
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
108 else if (is_digit(par[i])) dig++;
1152 else throw_err_block(0, err_invalid_version_number);
1153 }
1154
3/8
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 36 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
36 if (!dig || !dots || dots>2) throw_err_block(0, err_invalid_version_number);
1155
2/3
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
36 string vers_buf = par;
1156
2/3
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
36 autoptr<char**> vers = split(vers_buf.raw(), '.');
1157
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
36 int vermaj=atoi(vers[0]);
1158
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
36 if (vermaj > asarver_maj) throw_err_fatal(pass, err_asar_too_old);
1159
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 6 times.
36 if (vermaj < asarver_maj) return;
1160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (dots==1) {
1161 // todo: probably want to allow some more stuff here (it bans "asar 2.0" right now)
1162 if (strlen(vers[1])!=2) throw_err_block(0, err_invalid_version_number);
1163 int verminbug=atoi(vers[1]);
1164 int tmpver=asarver_bug;
1165 if (tmpver>9) tmpver=9;
1166 if (asarver_min*10+tmpver<verminbug) throw_err_fatal(pass, err_asar_too_old);
1167 } else {
1168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
6 int vermin = atoi(vers[1]);
1169
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6 if (vermin > asarver_min) throw_err_fatal(pass, err_asar_too_old);
1170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
6 int verbug = atoi(vers[2]);
1171
2/6
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
6 if (vermin == asarver_min && verbug > asarver_bug) throw_err_fatal(pass, err_asar_too_old);
1172 }
1173
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 30 times.
66 }
1174
1175 2 void cmd_include(const char* par) {
1176
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
2 if(!asarverallowed) throw_err_block(0, err_start_of_file);
1177
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if(*par) throw_err_block(0, err_broken_command, "include", "");
1178
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(in_top_level_file()) throw_err_fatal(pass, err_cant_be_main_file, "");
1179 }
1180
1181 6 void cmd_includefrom(const char* par) {
1182
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 if(!asarverallowed) throw_err_block(0, err_start_of_file);
1183 if(!*par) throw_err_block(0, err_broken_command, "include", "");
1184 if(in_top_level_file()) throw_err_fatal(pass, err_cant_be_main_file, (string(" The main file is '") + par + "'.").data());
1185 }
1186
1187 30 void cmd_includeonce(const char* par) {
1188
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 15 times.
30 if(*par) throw_err_block(0, err_broken_command, "includeonce", "");
1189
1190 30 const char* current_file = get_current_file_name();
1191
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 if (!file_included_once(current_file))
1192 {
1193
4/7
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 15 times.
✗ Branch 6 not taken.
30 includeonce.append(current_file);
1194 }
1195 30 }
1196
1197 900 void cmd_org(const char* par) {
1198
2/7
✗ Branch 0 not taken.
✓ Branch 1 taken 900 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 486 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
900 if(in_spcblock) throw_err_block(0, err_feature_unavaliable_in_spcblock);
1199
1/2
✓ Branch 0 taken 900 times.
✗ Branch 1 not taken.
900 freespaceend();
1200
2/3
✓ Branch 0 taken 414 times.
✓ Branch 1 taken 486 times.
✗ Branch 2 not taken.
900 auto math_expr = parse_math_expr(par);
1201
4/7
✓ Branch 0 taken 413 times.
✓ Branch 1 taken 486 times.
✓ Branch 2 taken 414 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 485 times.
✗ Branch 6 not taken.
900 int64_t num = math_expr->evaluate_non_forward().get_integer();
1202
1/9
✗ Branch 0 not taken.
✓ Branch 1 taken 898 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.
✗ Branch 8 not taken.
898 if (num&~0xFFFFFF) throw_err_block(1, err_snes_address_out_of_bounds, hex(num, 6).data());
1203
8/14
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 763 times.
✓ Branch 2 taken 150 times.
✓ Branch 3 taken 470 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 428 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 144 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 341 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
898 if ((mapper==lorom || mapper==exlorom) && (num&0x408000)==0x400000 && (num&0x700000)!=0x700000) throw_warning(0, warn_set_middle_byte);
1204 898 snespos=(int)num;
1205 898 realsnespos=(int)num;
1206 898 startpos=(int)num;
1207 898 realstartpos=(int)num;
1208 898 snespos_valid = true;
1209 1385 }
1210
1211 114 void cmd_struct(char** words, int numwords) {
1212 //verifysnespos();
1213
6/8
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 57 times.
✓ Branch 2 taken 57 times.
✓ Branch 3 taken 57 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 57 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 57 times.
114 if (in_struct || in_sub_struct) throw_err_block(0, err_nested_struct);
1214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
114 if (numwords < 1) throw_err_block(0, err_missing_struct_params);
1215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
114 if (numwords > 3) throw_err_block(0, err_too_many_struct_params);
1216
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
✓ Branch 2 taken 57 times.
114 if (!confirmname(words[0])) throw_err_block(0, err_invalid_struct_name);
1217
1218
7/7
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 57 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 27 times.
✓ Branch 4 taken 27 times.
✓ Branch 5 taken 57 times.
✓ Branch 6 taken 57 times.
114 if (structs.exists(words[0]) && pass == 0) throw_err_block(0, err_struct_redefined, words[0]);
1219
1220 114 static_struct = false;
1221 114 old_snespos = snespos;
1222 114 old_startpos = startpos;
1223 114 old_optimizeforbank = optimizeforbank;
1224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
114 old_snespos_valid = snespos_valid;
1225 114 unsigned int base = 0;
1226
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 66 times.
114 if (numwords == 2)
1227 {
1228 48 static_struct = true;
1229
2/4
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
48 auto base_expr = parse_math_expr(words[1]);
1230
4/7
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 23 times.
✗ Branch 6 not taken.
48 base = base_expr->evaluate_non_forward().get_integer();
1231
1232
4/8
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 23 times.
✓ Branch 4 taken 23 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 23 times.
46 if (base_expr->has_label() > 1) static_struct = false;
1233
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 14 times.
46 if (pass > 0) {
1234 // foundlabel_static isn't accurate anymore
1235
8/13
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 15 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 15 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 15 times.
32 if(structs.exists(words[0])) static_struct &= structs.find(words[0]).is_static;
1236 }
1237 48 }
1238
1239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
112 bool old_in_struct = in_struct;
1240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
112 bool old_in_sub_struct = in_sub_struct;
1241
4/4
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 46 times.
✓ Branch 3 taken 30 times.
112 in_struct = numwords == 1 || numwords == 2;
1242 112 in_sub_struct = numwords == 3;
1243
1244 #define cleanup() (in_struct = old_in_struct, in_sub_struct = old_in_sub_struct)
1245
1246
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 66 times.
112 if (numwords == 2)
1247 {
1248
1/9
✗ 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.
✗ Branch 8 not taken.
46 if (base&~0xFFFFFF) cleanup(), throw_err_block(0, err_snes_address_out_of_bounds, hex((unsigned int)base, 6).data());
1249 46 snespos = (int)base;
1250 46 startpos = (int)base;
1251 }
1252
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 36 times.
66 else if (numwords == 3)
1253 {
1254
3/8
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 30 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 15 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
30 if (strcasecmp(words[1], "extends")) cleanup(), throw_err_block(0, err_missing_extends);
1255
3/9
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 15 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
30 if (!confirmname(words[2])) cleanup(), throw_err_block(0, err_struct_invalid_parent_name);
1256
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
30 string tmp_struct_parent = words[2];
1257
1258
2/6
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 30 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
30 if (!structs.exists(tmp_struct_parent)) cleanup(), throw_err_block(0, err_struct_not_found, tmp_struct_parent.data());
1259
4/7
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 15 times.
✗ Branch 6 not taken.
30 snes_struct structure = structs.find(tmp_struct_parent);
1260
1261
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
30 static_struct = structure.is_static;
1262
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 struct_parent = tmp_struct_parent;
1263 30 snespos = structure.base_end;
1264 30 startpos = structure.base_end;
1265 30 }
1266
1267 112 push_pc();
1268
1269 112 optimizeforbank = -1;
1270
1271 112 struct_name = words[0];
1272 112 struct_base = snespos;
1273 112 realsnespos = 0;
1274 112 realstartpos = 0;
1275 112 snespos_valid = true;
1276
1277
4/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 97 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 41 times.
112 if(in_sub_struct) {
1278
3/7
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 15 times.
✗ Branch 6 not taken.
30 string labelname = struct_parent + "." + struct_name;
1279
5/8
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 15 times.
✗ Branch 7 not taken.
30 setlabel(ns + labelname, snespos, static_struct);
1280 30 } else {
1281
5/8
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 41 times.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 41 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 41 times.
✗ Branch 7 not taken.
82 setlabel(ns + struct_name, snespos, static_struct);
1282 }
1283
1284 #undef cleanup
1285 112 }
1286
1287 114 void cmd_endstruct(char** words, int numwords) {
1288
3/6
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
114 if (numwords != 0 && numwords != 2) throw_err_block(0, err_invalid_endstruct_count);
1289
6/10
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 57 times.
✓ Branch 6 taken 57 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
114 if (numwords == 2 && stricmpwithlower(words[0], "align")) throw_err_block(0, err_expected_align);
1290
9/10
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 98 times.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 56 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 16 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 15 times.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
114 if (!in_struct && !in_sub_struct) throw_err_block(0, err_endstruct_without_struct);
1291
1292
4/6
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 106 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
112 int alignment = numwords == 2 ? (int)getnum(words[1]) : 1;
1293
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
112 if (alignment < 1) throw_err_block(0, err_alignment_too_small);
1294
1295 112 snes_struct structure;
1296 112 structure.base_end = snespos;
1297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
112 structure.struct_size = alignment * ((snespos - struct_base + alignment - 1) / alignment);
1298 112 structure.object_size = structure.struct_size;
1299
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
112 structure.is_static = static_struct;
1300
1301
4/4
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 71 times.
✓ Branch 2 taken 41 times.
✓ Branch 3 taken 15 times.
112 if (in_struct)
1302 {
1303
3/5
✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41 times.
✓ Branch 3 taken 41 times.
✗ Branch 4 not taken.
82 structs.create(struct_name) = structure;
1304 }
1305
3/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
30 else if (in_sub_struct)
1306 {
1307 30 snes_struct parent;
1308
3/5
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
30 parent = structs.find(struct_parent);
1309
1310
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 6 times.
30 if (parent.object_size < parent.struct_size + structure.struct_size) {
1311 24 parent.object_size = parent.struct_size + structure.struct_size;
1312 }
1313
1314
7/13
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✓ Branch 5 taken 15 times.
✓ Branch 6 taken 15 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 15 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 15 times.
✗ Branch 12 not taken.
30 structs.create(struct_parent + "." + struct_name) = structure;
1315
3/5
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
30 structs.create(struct_parent) = parent;
1316 30 }
1317
1318
1/2
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
112 pop_pc();
1319 112 in_struct = false;
1320 112 in_sub_struct = false;
1321 112 snespos = old_snespos;
1322 112 startpos = old_startpos;
1323 112 optimizeforbank = old_optimizeforbank;
1324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
112 snespos_valid = old_snespos_valid;
1325 112 static_struct = false;
1326 168 }
1327
1328 12 void cmd_spcblock(char** words, int num_words) {
1329 12 int addrToLinePos = realsnespos & 0xFFFFFF;
1330 //banned features when active: org, freespace(and variants), arch, mapper,namespace,pushns
1331
6/8
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
12 if(in_struct || in_sub_struct) throw_err_block(0, err_spcblock_inside_struct);
1332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if(num_words < 1) throw_err_block(0, err_spcblock_too_few_args);
1333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if(num_words > 3) throw_err_block(0, err_spcblock_too_many_args);
1334
1335 12 spcblock.destination = getnum(words[0]);
1336 12 spcblock.type = spcblock_nspc;
1337 12 spcblock.macro_name = "";
1338
1339
1/9
✗ Branch 0 not taken.
✓ Branch 1 taken 12 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.
✗ Branch 8 not taken.
12 if (spcblock.destination&~0xFFFF) throw_err_block(0, err_snes_address_out_of_bounds, hex(spcblock.destination, 6).data());
1340
1341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if(num_words == 2)
1342 {
1343 if(!stricmp(words[1], "nspc")) spcblock.type = spcblock_nspc;
1344 else if(!stricmp(words[1], "custom")) throw_err_block(0, err_custom_spcblock_missing_macro);
1345 else throw_err_block(0, err_unknown_spcblock_type);
1346 }
1347
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 else if(num_words == 3)
1348 {
1349 if(!stricmp(words[1], "custom")) spcblock.type = spcblock_custom;
1350 else throw_err_block(0, err_extra_spcblock_arg_for_type);
1351
1352 if(macros.exists(words[2]))
1353 {
1354 macrodata *macro = macros.find(words[2]);
1355 if(!macro->variadic) throw_err_block(0, err_spcblock_macro_must_be_varadic);
1356 if(macro->numargs != 3) throw_err_block(0, err_spcblock_macro_invalid_static_args);
1357 spcblock.macro_name = words[2];
1358 }
1359 else throw_err_block(0, err_spcblock_macro_doesnt_exist);
1360 }
1361
1362
3/5
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12 switch(spcblock.type)
1363 {
1364 12 case spcblock_nspc:
1365 12 spcblock.size_address=realsnespos;
1366 12 write2(0x0000);
1367 12 write2(spcblock.destination);
1368 12 snespos=(int)spcblock.destination;
1369 12 startpos=(int)spcblock.destination;
1370 12 add_addr_to_line(addrToLinePos);
1371 12 break;
1372 case spcblock_custom:
1373 //this is a todo that probably won't be ready for 1.9
1374 //mostly so we can leverage some cleanups we make in 2.0 for practicality
1375 throw_err_block(0, err_spcblock_custom_types_incomplete);
1376 push_pc();
1377 spcblock.old_mapper = mapper;
1378 mapper = norom;
1379 break;
1380 default:
1381 throw_err_fatal(0, err_internal_error, "invalid spcblock type");
1382 }
1383
1384 12 ns_backup = ns;
1385
3/7
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
12 ns = STR":SPCBLOCK:_" + ns_backup;
1386 12 in_spcblock = true;
1387 12 }
1388
1389 12 void cmd_endspcblock(char** words, int num_words) {
1390
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
12 if(!in_spcblock) throw_err_block(0, err_endspcblock_without_spcblock);
1391
1392
3/5
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12 switch(spcblock.type)
1393 {
1394 12 case spcblock_nspc:
1395
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8 times.
12 if (pass==2)
1396 {
1397 4 int pcpos=snestopc(spcblock.size_address&0xFFFFFF);
1398
1/9
✗ Branch 0 not taken.
✓ Branch 1 taken 4 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.
✗ Branch 8 not taken.
4 if (pcpos<0) throw_err_block(2, err_snes_address_doesnt_map_to_rom, hex((unsigned int)realsnespos, 6).data());
1399 // compute number of bytes written;
1400 // offset by 4 for the spcblock header itself
1401 4 int num = realsnespos - ((int)spcblock.size_address + 4);
1402 4 writeromdata_byte(pcpos, (unsigned char)num);
1403 4 writeromdata_byte(pcpos+1, (unsigned char)(num >> 8));
1404 }
1405
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (num_words == 2)
1406 {
1407 // todo allow spaces here
1408
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
6 if (strcmp(words[0], "execute")) throw_err_null(0, err_invalid_endspcblock_arg, words[0]);
1409 else
1410 {
1411 6 write2(0x0000);
1412
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 write2(pass == 2 ? (unsigned int)getnum(words[1]) : 0);
1413 }
1414 }
1415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 else if (num_words != 0)
1416 {
1417 throw_err_null(0, err_unknown_endspcblock_format);
1418 }
1419 12 break;
1420 case spcblock_custom:
1421 mapper = spcblock.old_mapper;
1422 pop_pc();
1423 break;
1424 default:
1425 throw_err_fatal(0, err_internal_error, "invalid spcblock type");
1426 }
1427 12 ns = ns_backup;
1428 12 in_spcblock = false;
1429 12 snespos=realsnespos;
1430 12 startpos=realstartpos;
1431 12 }
1432
1433 102 void cmd_base(const char* par) {
1434
4/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 87 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 36 times.
102 if (!stricmp(par, "off"))
1435 {
1436 30 snespos=realsnespos;
1437 30 startpos=realstartpos;
1438 30 snespos_valid = realsnespos >= 0;
1439 30 return;
1440 }
1441
5/10
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 36 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 36 times.
✗ Branch 9 not taken.
72 unsigned int num=parse_math_expr(par)->evaluate_non_forward().get_integer();
1442
1/9
✗ Branch 0 not taken.
✓ Branch 1 taken 72 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.
✗ Branch 8 not taken.
72 if (num&~0xFFFFFF) throw_err_block(1, err_snes_address_out_of_bounds, hex((unsigned int)num).data());
1443 72 snespos=(int)num;
1444 72 startpos=(int)num;
1445 72 optimizeforbank=-1;
1446 72 snespos_valid = realsnespos >= 0;
1447 }
1448
1449 12 void cmd_dpbase(const char* par) {
1450
5/10
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 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.
12 unsigned int num=parse_math_expr(par)->evaluate_non_forward().get_integer();
1451
1/9
✗ Branch 0 not taken.
✓ Branch 1 taken 12 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.
✗ Branch 8 not taken.
12 if (num&~0xFF00) throw_err_block(1, err_bad_dp_base, hex((unsigned int)num, 6).data());
1452 12 dp_base = (int)num;
1453 12 }
1454
1455 102 void cmd_optimize(char** words, int num_words) {
1456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102 times.
102 if(num_words != 2) throw_err_block(1, err_bad_optimize, "");
1457
1458
5/5
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 51 times.
✓ Branch 3 taken 21 times.
✓ Branch 4 taken 30 times.
102 if (!stricmp(words[0], "dp"))
1459 {
1460
5/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 9 times.
42 if (!stricmp(words[1], "none"))
1461 {
1462 24 optimize_dp = optimize_dp_flag::NONE;
1463 24 return;
1464 }
1465
5/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 6 times.
18 if (!stricmp(words[1], "ram"))
1466 {
1467 6 optimize_dp = optimize_dp_flag::RAM;
1468 6 return;
1469 }
1470
3/6
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
12 if (!stricmp(words[1], "always"))
1471 {
1472 12 optimize_dp = optimize_dp_flag::ALWAYS;
1473 12 return;
1474 }
1475 throw_err_block(1, err_bad_dp_optimize, words[1]);
1476 }
1477
3/5
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 30 times.
✗ Branch 4 not taken.
60 if (!stricmp(words[0], "address"))
1478 {
1479
5/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 30 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 18 times.
60 if (!stricmp(words[1], "default"))
1480 {
1481 24 optimize_address = optimize_address_flag::DEFAULT;
1482 24 return;
1483 }
1484
5/6
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 9 times.
36 if (!stricmp(words[1], "ram"))
1485 {
1486 18 optimize_address = optimize_address_flag::RAM;
1487 18 return;
1488 }
1489
3/6
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
18 if (!stricmp(words[1], "mirrors"))
1490 {
1491 18 optimize_address = optimize_address_flag::MIRRORS;
1492 18 return;
1493 }
1494 throw_err_block(1, err_bad_address_optimize, words[1]);
1495 }
1496 throw_err_block(1, err_bad_optimize, words[0]);
1497 }
1498
1499 18 void cmd_bank(const char* par) {
1500
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 6 times.
18 if (!stricmp(par, "auto"))
1501 {
1502 6 optimizeforbank=-1;
1503 6 return;
1504 }
1505
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
12 if (!stricmp(par, "noassume"))
1506 {
1507 6 optimizeforbank=0x140;
1508 6 return;
1509 }
1510 6 unsigned int num=getnum(par);
1511 //if (forwardlabel) error(0, "bank Label is not valid");
1512 //if (foundlabel) num>>=16;
1513
1/9
✗ Branch 0 not taken.
✓ Branch 1 taken 6 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.
✗ Branch 8 not taken.
6 if (num&~0x0000FF) throw_err_block(1, err_snes_address_out_of_bounds, hex((unsigned int)num, 6).data());
1514 6 optimizeforbank=(int)num;
1515 }
1516
1517 enum class freespace_cmds {
1518 freespace,
1519 freecode,
1520 freedata,
1521 segment,
1522 };
1523
1524 template<freespace_cmds the_cmd>
1525 3132 void cmd_freespace(const char* par) {
1526
2/7
✗ Branch 0 not taken.
✓ Branch 1 taken 1566 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 783 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
3132 if(in_spcblock) throw_err_block(0, err_feature_unavaliable_in_spcblock);
1527
1528
2/3
✓ Branch 0 taken 783 times.
✓ Branch 1 taken 783 times.
✗ Branch 2 not taken.
3132 freespace_data this_fs_settings = default_freespace_settings;
1529 2244 if (the_cmd == freespace_cmds::freecode) this_fs_settings.bank = -2;
1530 672 if (the_cmd == freespace_cmds::freedata) this_fs_settings.bank = -1;
1531 204 if (the_cmd == freespace_cmds::segment) this_fs_settings.write_rats = false;
1532
1533
2/3
✓ Branch 0 taken 783 times.
✓ Branch 1 taken 783 times.
✗ Branch 2 not taken.
3132 string parstr = par;
1534
1/2
✓ Branch 0 taken 1566 times.
✗ Branch 1 not taken.
3132 parse_freespace_arguments(this_fs_settings, parstr);
1535
1536
5/6
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 1500 times.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 33 times.
✓ Branch 4 taken 33 times.
✗ Branch 5 not taken.
3132 if(this_fs_settings.bank == -3 && !this_fs_settings.write_rats) this_fs_settings.bank = -1;
1537
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1566 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3132 if(this_fs_settings.bank == -3) throw_err_block(0, err_invalid_freespace_request);
1538 // no point specifying anything about cleaning when not writing a rats tag
1539
4/4
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 1515 times.
✓ Branch 2 taken 51 times.
✓ Branch 3 taken 732 times.
3132 if(!this_fs_settings.write_rats &&
1540
6/8
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 51 times.
✓ Branch 3 taken 51 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 51 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 51 times.
204 (this_fs_settings.flag_cleaned || this_fs_settings.is_static))
1541 throw_err_block(0, err_invalid_freespace_request);
1542
4/4
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 1515 times.
✓ Branch 2 taken 51 times.
✓ Branch 3 taken 732 times.
3132 if(!this_fs_settings.write_rats) this_fs_settings.flag_cleaned = true;
1543
1/2
✓ Branch 0 taken 1566 times.
✗ Branch 1 not taken.
3132 freespaceend();
1544 3132 freespaceid = freespaceidnext++;
1545
1/2
✓ Branch 0 taken 1566 times.
✗ Branch 1 not taken.
3132 freespace_data& thisfs = freespaces[freespaceid];
1546
1547
2/2
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 1044 times.
3132 if (pass==0) {
1548
2/3
✓ Branch 0 taken 261 times.
✓ Branch 1 taken 261 times.
✗ Branch 2 not taken.
1044 thisfs = this_fs_settings;
1549 1044 thisfs.pos = -1;
1550 1044 thisfs.leaked = true;
1551 1044 thisfs.orgpos = -2;
1552 1044 thisfs.orglen = -1;
1553 1044 snespos=0;
1554 }
1555
2/2
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 1044 times.
3132 if (pass==1)
1556 {
1557
6/7
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 259 times.
✓ Branch 2 taken 261 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 259 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
1044 if (thisfs.is_static && thisfs.orgpos == -2)
1558 {
1559 thisfs.pos = 0;
1560 thisfs.leaked = false;//mute some other errors
1561 throw_err_block(1, err_static_freespace_autoclean);
1562 }
1563 1044 snespos = 0;
1564 }
1565
2/2
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 1044 times.
3132 if (pass==2)
1566 {
1567
6/7
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 259 times.
✓ Branch 2 taken 261 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 259 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
1044 if (thisfs.is_static && thisfs.orgpos == -2) return;//to kill some errors (supposedly????)
1568 1044 snespos=thisfs.pos;
1569
7/12
✓ Branch 0 taken 228 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 261 times.
✓ Branch 3 taken 456 times.
✓ Branch 4 taken 33 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 228 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 228 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
1044 if (thisfs.leaked && !thisfs.flag_cleaned) throw_warning(2, warn_freespace_leaked);
1570
5/5
✓ Branch 0 taken 244 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 261 times.
✓ Branch 3 taken 244 times.
✓ Branch 4 taken 17 times.
1044 freespaceuse += (thisfs.write_rats ? 8 : 0) + thisfs.len;
1571
1572 // add a mapping for the start of the rats tag
1573
6/7
✓ Branch 0 taken 244 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 505 times.
✓ Branch 3 taken 244 times.
✓ Branch 4 taken 17 times.
✓ Branch 5 taken 244 times.
✗ Branch 6 not taken.
1044 if (thisfs.write_rats) add_addr_to_line(snespos-8);
1574 }
1575
1/12
✗ Branch 0 not taken.
✓ Branch 1 taken 1566 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.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
3132 if (snespos < 0 && mapper == sa1rom) throw_err_fatal(pass, err_no_freespace_in_mapped_banks, dec(thisfs.len).data());
1576
1/9
✗ Branch 0 not taken.
✓ Branch 1 taken 1566 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.
✗ Branch 8 not taken.
3132 if (snespos < 0) throw_err_fatal(pass, err_no_freespace, dec(thisfs.len).data());
1577
5/5
✓ Branch 0 taken 732 times.
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 783 times.
✓ Branch 3 taken 732 times.
✓ Branch 4 taken 51 times.
3132 bytes+=thisfs.write_rats ? 8 : 0;
1578 3132 freespacestart=snespos;
1579 3132 startpos=snespos;
1580 3132 realstartpos=snespos;
1581 3132 realsnespos=snespos;
1582 3132 optimizeforbank=-1;
1583
5/5
✓ Branch 0 taken 732 times.
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 783 times.
✓ Branch 3 taken 732 times.
✓ Branch 4 taken 51 times.
3132 ratsmetastate=thisfs.write_rats ? ratsmeta_allow : ratsmeta_ban;
1584 3132 snespos_valid = true;
1585 // check this at the very end so that snespos gets set properly, to
1586 // prevent spurious errors later
1587 //...i guess this can still cause bankcross errors if the old freespace
1588 //happened to be very close to the end of a bank or something, but
1589 //whatever
1590
10/12
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 1044 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 259 times.
✓ Branch 4 taken 262 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 260 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
3132 if (pass == 2 && thisfs.is_static && thisfs.orgpos > 0 && thisfs.len > thisfs.orglen)
1591
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 throw_err_block(2, err_static_freespace_growing);
1592
2/4
✓ Branch 0 taken 1564 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1564 times.
✗ Branch 3 not taken.
3136 }
1593
1594 6 void cmd_freespace_settings(const char* par) {
1595
2/3
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 string arg = par;
1596
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 parse_freespace_arguments(default_freespace_settings, arg);
1597 9 }
1598
1599 42 void cmd_prot(const char* par) {
1600 42 int addrToLinePos = realsnespos & 0xFFFFFF;
1601
2/7
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
42 if(in_spcblock) throw_err_block(0, err_feature_unavaliable_in_spcblock);
1602
2/7
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
42 if (!ratsmetastate) throw_err_block(2, err_prot_not_at_freespace_start);
1603
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 15 times.
42 if (ratsmetastate==ratsmeta_used) step(-5);
1604 21 int num;
1605
2/3
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
42 string parbuf = par;
1606
2/3
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
42 autoptr<char**> pars=qpsplit(parbuf.raw(), ',', &num);
1607
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 verify_paren(pars);
1608
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 write1('P');
1609
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 write1('R');
1610
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 write1('O');
1611
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 write1('T');
1612
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
42 if (num * 3 > 255) throw_err_block(0, err_prot_too_many_entries);
1613
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 write1((unsigned int)(num*3));
1614
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 42 times.
96 for (int i=0;i<num;i++)
1615 {
1616 54 const char * labeltest=pars[i];
1617
2/3
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
54 string testlabel = labeltest;
1618
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 snes_label lblval = labelval(&labeltest);
1619
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
54 if (*labeltest) throw_err_block(0, err_label_not_found, testlabel.data());
1620
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 write3(lblval.pos);
1621
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
54 if (pass==1) freespaces[lblval.freespace_id].leaked = false;
1622 54 }
1623
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 write1('S');
1624
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 write1('T');
1625
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 write1('O');
1626
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 write1('P');
1627
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 write1(0);
1628 42 ratsmetastate=ratsmeta_used;
1629
1630
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 add_addr_to_line(addrToLinePos);
1631 63 }
1632
1633 18 void cmd_autoclean(char** words, int num_words) {
1634
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
18 if(in_spcblock) throw_err_block(0, err_feature_unavaliable_in_spcblock);
1635
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (num_words==2)
1636 {
1637 18 const char * labeltest = words[1];
1638
2/3
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
18 string testlabel = labeltest;
1639
2/3
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
18 if(!stricmpwithlower(words[0], "dl")) {
1640
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 handle_autoclean(testlabel, -1, snespos);
1641
1642
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 add_addr_to_line(realsnespos & 0xFFFFFF);
1643
12/20
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 15 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 3 times.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✓ Branch 15 taken 6 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
18 write3(pass==2 ? labelval(testlabel).pos : 0);
1644 } else {
1645 // other ones are handled in arch-65816
1646 throw_err_block(0, err_broken_autoclean);
1647 }
1648 18 }
1649 else if (num_words == 1) {
1650 if(pass==0) removerats(parse_math_expr(words[0])->evaluate_static().get_integer(), freespacebyte);
1651 } else {
1652 throw_err_block(0, err_broken_autoclean);
1653 }
1654 18 }
1655
1656 6 void cmd_freespacebyte(const char* par) {
1657
5/10
✓ Branch 0 taken 3 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.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
6 freespacebyte = parse_math_expr(par)->evaluate_static().get_integer();
1658 6 }
1659
1660 6 void cmd_pushpc(const char* par) {
1661
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
6 if(*par) throw_err_block(0, err_broken_command, "pushpc", "");
1662 6 verifysnespos();
1663 6 pushpc[pushpcnum].arch=arch;
1664 6 pushpc[pushpcnum].snespos=snespos;
1665 6 pushpc[pushpcnum].snesstart=startpos;
1666 6 pushpc[pushpcnum].snesposreal=realsnespos;
1667 6 pushpc[pushpcnum].snesstartreal=realstartpos;
1668 6 pushpc[pushpcnum].freeid=freespaceid;
1669 6 pushpc[pushpcnum].freest=freespacestart;
1670 6 pushpcnum++;
1671 6 snespos=(int)0xFFFFFFFF;
1672 6 startpos= (int)0xFFFFFFFF;
1673 6 realsnespos= (int)0xFFFFFFFF;
1674 6 realstartpos= (int)0xFFFFFFFF;
1675 6 snespos_valid = false;
1676 6 }
1677
1678 6 void cmd_pullpc(const char* par) {
1679
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
6 if(*par) throw_err_block(0, err_broken_command, "pullpc", "");
1680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!pushpcnum) throw_err_block(0, err_pullpc_without_pushpc);
1681 6 pushpcnum--;
1682 6 freespaceend();
1683
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
6 if (arch != pushpc[pushpcnum].arch) throw_err_block(0, err_pullpc_different_arch);
1684 6 snespos=pushpc[pushpcnum].snespos;
1685 6 startpos=pushpc[pushpcnum].snesstart;
1686 6 realsnespos=pushpc[pushpcnum].snesposreal;
1687 6 realstartpos=pushpc[pushpcnum].snesstartreal;
1688 6 freespaceid=pushpc[pushpcnum].freeid;
1689 6 freespacestart=pushpc[pushpcnum].freest;
1690 6 snespos_valid = true;
1691 6 }
1692
1693 6 void cmd_pushbase(const char* par) {
1694
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
6 if(*par) throw_err_block(0, err_broken_command, "pushbase", "");
1695 6 basestack[basestacknum] = snespos;
1696 6 basestacknum++;
1697 6 }
1698
1699 6 void cmd_pullbase(const char* par) {
1700
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
6 if(*par) throw_err_block(0, err_broken_command, "pullbase", "");
1701
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!basestacknum) throw_err_block(0, err_pullbase_without_pushbase);
1702 6 basestacknum--;
1703 6 snespos = basestack[basestacknum];
1704 6 startpos = basestack[basestacknum];
1705
1706
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (snespos != realstartpos)
1707 {
1708 6 optimizeforbank = -1;
1709 }
1710 6 }
1711
1712 12 void cmd_pushns(const char* par) {
1713
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
12 if(*par) throw_err_block(0, err_broken_command, "pushns", "");
1714
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
12 if(in_spcblock) throw_err_block(0, err_feature_unavaliable_in_spcblock);
1715 12 pushns[pushnsnum].ns = ns;
1716
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for(int i = 0; i < namespace_list.count; i++)
1717 {
1718 12 pushns[pushnsnum].namespace_list.append(namespace_list[i]);
1719 }
1720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
12 pushns[pushnsnum].nested_namespaces = nested_namespaces;
1721 12 pushnsnum++;
1722
1723 12 namespace_list.reset();
1724 12 ns = "";
1725 12 nested_namespaces = false;
1726 12 }
1727
1728 12 void cmd_pullns(const char* par) {
1729
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
12 if(*par) throw_err_block(0, err_broken_command, "pullns", "");
1730
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
12 if(in_spcblock) throw_err_block(0, err_feature_unavaliable_in_spcblock);
1731
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!pushnsnum) throw_err_block(0, err_pullns_without_pushns);
1732 12 pushnsnum--;
1733 12 ns = pushns[pushnsnum].ns;
1734
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
12 nested_namespaces = pushns[pushnsnum].nested_namespaces;
1735 12 namespace_list.reset();
1736
4/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 6 times.
36 for(int i = 0; i < pushns[pushnsnum].namespace_list.count; i++)
1737 {
1738 24 namespace_list.append(pushns[pushnsnum].namespace_list[i]);
1739 }
1740 12 }
1741
1742 165 void cmd_namespace(char** words, int num_words) {
1743
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 165 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 84 times.
165 if(in_spcblock) throw_err_block(0, err_feature_unavaliable_in_spcblock);
1744 165 bool leave = false;
1745
1/2
✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
165 if (num_words >= 1)
1746 {
1747
5/5
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 57 times.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 24 times.
✓ Branch 4 taken 60 times.
165 if (!stricmp(words[0], "off"))
1748 {
1749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (num_words != 1) throw_err_block(0, err_invalid_namespace_use);
1750 48 leave = true;
1751 }
1752
5/5
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 42 times.
117 else if (!stricmp(words[0], "nested"))
1753 {
1754
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (num_words != 2) throw_err_block(0, err_invalid_namespace_use);
1755
5/6
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 9 times.
36 else if (!stricmp(words[1], "on")) nested_namespaces = true;
1756
3/6
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
18 else if (!stricmp(words[1], "off")) nested_namespaces = false;
1757 }
1758 else
1759 {
1760
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 if (num_words != 1) throw_err_block(0, err_invalid_namespace_use);
1761 81 const char * tmpstr= safedequote(words[0]);
1762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 if (!confirmname(tmpstr)) throw_err_block(0, err_invalid_namespace_name);
1763
4/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 24 times.
81 if (!nested_namespaces)
1764 {
1765 33 namespace_list.reset();
1766 }
1767
4/7
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 39 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 42 times.
✗ Branch 6 not taken.
81 namespace_list.append(tmpstr);
1768 }
1769 }
1770 else
1771 {
1772 throw_err_block(0, err_invalid_namespace_use);
1773 //leave = true;
1774 }
1775
1776
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 117 times.
165 if (leave)
1777 {
1778
4/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 6 times.
48 if (nested_namespaces)
1779 {
1780 36 namespace_list.remove(namespace_list.count - 1);
1781 }
1782 else
1783 {
1784 12 namespace_list.reset();
1785 }
1786 }
1787
1788 // recompute ns
1789 165 ns = "";
1790
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 165 times.
360 for (int i = 0; i < namespace_list.count; i++)
1791 {
1792 195 ns += namespace_list[i];
1793 195 ns += "_";
1794 }
1795 165 }
1796
1797 10171 void cmd_incsrc(const char* par) {
1798 // RPG Hacker: Should this also throw on absolute paths?
1799 // E.g., on something starting with C:/ or whatever.
1800
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10168 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 5093 times.
10171 if (strchr(par, '\\'))
1801 {
1802
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 throw_err_block(0, err_platform_paths);
1803 }
1804
2/3
✓ Branch 0 taken 5072 times.
✓ Branch 1 taken 5093 times.
✗ Branch 2 not taken.
10165 string temp = par;
1805
1/2
✓ Branch 0 taken 10165 times.
✗ Branch 1 not taken.
10165 const char* name = safedequote(temp.raw());
1806
2/2
✓ Branch 0 taken 159 times.
✓ Branch 1 taken 10006 times.
10165 assemblefile(name);
1807 10255 }
1808
1809 60 void cmd_incbin(const char* par) {
1810 60 int addrToLinePos = realsnespos & 0xFFFFFF;
1811 30 int len;
1812 60 int start=0;
1813 60 int end=0;
1814
2/3
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
60 string temp = par;
1815 60 const char* lengths = strqchr(temp, ':');
1816
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 30 times.
60 if (lengths)
1817 {
1818 30 lengths++;
1819
1820
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 const char* split = strqpstr(lengths, "..");
1821
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
30 if(!split) throw_err_block(0, err_broken_incbin);
1822
2/3
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
24 string start_str(lengths, split-lengths);
1823
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
24 if(start_str == "") throw_err_block(0, err_broken_incbin);
1824
5/10
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 12 times.
✗ Branch 9 not taken.
24 start = parse_math_expr(start_str)->evaluate_non_forward().get_integer();
1825
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
24 string end_str(split+2);
1826
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
24 if(end_str == "") throw_err_block(0, err_broken_incbin);
1827
5/10
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 12 times.
✗ Branch 9 not taken.
24 end = parse_math_expr(end_str)->evaluate_non_forward().get_integer();
1828 // make temp just the filename without the lengths
1829
2/3
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
24 temp.truncate(lengths-1 - temp.data());
1830 24 }
1831
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 const char* current_file = get_current_file_name();
1832 // RPG Hacker: Should this also throw on absolute paths?
1833 // E.g., on something starting with C:/ or whatever.
1834
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 24 times.
54 if (strchr(par, '\\'))
1835 {
1836
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 throw_err_block(0, err_platform_paths);
1837 }
1838
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 const char* name = safedequote(temp.raw());
1839
1840 24 char * data;//I couldn't find a way to get this into an autoptr
1841
5/8
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 36 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
48 if (!readfile(name, current_file, &data, &len)) throw_vfile_error(0, asar_get_last_io_error(), name);
1842 36 autoptr<char*> datacopy=data;
1843
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 24 times.
36 if (!end) end=len;
1844
1/9
✗ Branch 0 not taken.
✓ Branch 1 taken 36 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.
✗ Branch 8 not taken.
36 if(start < 0) throw_err_block(1, err_file_offset_out_of_bounds, dec(start).data(), name);
1845
3/13
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 36 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
36 if (end < start || end > len || end < 0) throw_err_block(1, err_file_offset_out_of_bounds, dec(end).data(), name);
1846
1847
5/6
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 33 times.
✓ Branch 5 taken 18 times.
102 for (int i=start;i<end;i++) write1((unsigned int)data[i]);
1848
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 add_addr_to_line(addrToLinePos);
1849 78 }
1850
1851 template<bool is_fill>
1852 1344 void cmd_skip_fill(char** words, int num_words) {
1853 1344 const char* cmdname = is_fill ? "fill" : "skip";
1854
4/6
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 666 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
1344 if(num_words != 1 && num_words != 2 && num_words != 4) throw_err_block(0, err_broken_command, cmdname, "");
1855
6/7
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 666 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 336 times.
✓ Branch 6 taken 3 times.
1344 if(num_words > 1 && stricmp(words[0], "align")) throw_err_block(0, err_broken_command, cmdname, "expected \"align\"");
1856
5/8
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 666 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 339 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
1344 if(num_words == 4 && stricmp(words[2], "offset")) throw_err_block(0, err_broken_command, cmdname, "expected \"offset\"");
1857 int amount;
1858
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 666 times.
1344 if(num_words > 1)
1859 {
1860
5/10
✓ Branch 0 taken 3 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.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
12 int alignment = parse_math_expr(words[1])->evaluate_static().get_integer();
1861 12 int offset = 0;
1862
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
12 if(num_words==4)
1863 {
1864
5/10
✓ Branch 0 taken 3 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.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
12 offset = parse_math_expr(words[3])->evaluate_static().get_integer();
1865 }
1866
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
12 if(alignment > 0x800000) throw_err_block(0, err_alignment_too_big);
1867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
12 if(alignment < 1) throw_err_block(0, err_alignment_too_small);
1868
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
12 if(alignment & (alignment-1)) throw_err_block(0, err_invalid_alignment);
1869 // i just guessed this formula but it seems to work
1870 12 amount = (alignment - ((snespos - offset) & (alignment-1))) & (alignment-1);
1871 // TODO: set current freespace align to at least alignment
1872 }
1873 else
1874 {
1875
5/10
✓ Branch 0 taken 333 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 666 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 333 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 333 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 333 times.
✗ Branch 9 not taken.
1332 amount = parse_math_expr(words[0])->evaluate_non_forward().get_integer();
1876 }
1877 1212 if(!is_fill) step(amount);
1878 else
1879 {
1880 132 add_addr_to_line(realsnespos & 0xFFFFFF);
1881
4/4
✓ Branch 0 taken 203535 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 203535 times.
✓ Branch 3 taken 33 times.
814272 for(int i=0; i < amount; i++) write1(fillbyte[i%12]);
1882 }
1883 1344 }
1884
1885 6 void cmd_cleartable(const char* par) {
1886
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
6 if(*par) throw_err_block(0, err_broken_command, "cleartable", "");
1887 6 cleartable();
1888 6 }
1889
1890 6 void cmd_pushtable(const char* par) {
1891
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
6 if(*par) throw_err_block(0, err_broken_command, "pushtable", "");
1892 6 tablestack.append(thetable);
1893 6 }
1894
1895 6 void cmd_pulltable(const char* par) {
1896
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
6 if(*par) throw_err_block(0, err_broken_command, "pulltable", "");
1897
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (tablestack.count <= 0) throw_err_block(0, err_pulltable_without_table);
1898 6 thetable=tablestack[tablestack.count-1];
1899 6 tablestack.remove(tablestack.count-1);
1900 6 }
1901
1902 48 void cmd_function(const char* par) {
1903
2/3
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
48 string parbuf = par;
1904
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 parbuf.qnormalize(); // todo what's the point of doing this here in particular???
1905 48 char* name_and_args = parbuf.raw();
1906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
48 char* fn_body = strchr(name_and_args, '=');
1907
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
48 if(!fn_body) throw_err_block(0, err_broken_function_declaration);
1908 48 *fn_body = 0;
1909 48 fn_body++;
1910
2/6
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
48 if(!confirmqpar(name_and_args)) throw_err_block(0, err_broken_function_declaration);
1911 48 char* startpar = strqchr(name_and_args, '(');
1912
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
48 if (!startpar) throw_err_block(0, err_broken_function_declaration);
1913 48 *startpar = 0;
1914 48 startpar++;
1915
3/7
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
48 if(!confirmname(name_and_args)) throw_err_block(0, err_invalid_function_name);
1916 48 char* endpar = strqchr(startpar, ')');
1917 48 *endpar = 0;
1918 48 endpar++;
1919 // it's legal for there to be spaces between ) and =
1920
4/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 24 times.
96 while(*endpar == ' ') endpar++;
1921
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
48 if(*endpar) throw_err_block(0, err_broken_function_declaration);
1922
1923
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 createuserfunc(name_and_args, startpar, fn_body);
1924 72 }
1925
1926 324 void cmd_print(const char* par) {
1927
3/3
✓ Branch 0 taken 155 times.
✓ Branch 1 taken 165 times.
✓ Branch 2 taken 4 times.
324 string out = handle_print(par);
1928
3/4
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 216 times.
✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
316 if(pass == 2) print(out);
1929 477 }
1930
1931 6 void cmd_reset(const char* par) {
1932 if(0);
1933
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 else if (!stricmp(par, "bytes")) bytes=0;
1934 else if (!stricmp(par, "freespaceuse")) freespaceuse=0;
1935 else throw_err_block(2, err_unknown_variable);
1936 6 }
1937
1938 template<int width, bool is_fill>
1939 108 void cmd_padbytes(const char* par) {
1940
5/10
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 27 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 27 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 27 times.
✗ Branch 9 not taken.
108 unsigned int val = parse_math_expr(par)->evaluate_static().get_integer();
1941
2/2
✓ Branch 0 taken 510 times.
✓ Branch 1 taken 54 times.
1128 for (int i=0;i<12;i+=width)
1942 {
1943 1020 unsigned int tmpval=val;
1944
2/2
✓ Branch 0 taken 648 times.
✓ Branch 1 taken 510 times.
2316 for (int j=0;j<width;j++)
1945 {
1946 1296 (is_fill ? fillbyte : padbyte)[i+j] = (unsigned char)tmpval;
1947 1296 tmpval>>=8;
1948 }
1949 }
1950 108 }
1951
1952 12 void cmd_pad(const char* par) {
1953
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (freespaceid > 0) throw_err_block(0, err_pad_in_freespace);
1954
5/10
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 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.
12 int num = parse_math_expr(par)->evaluate_non_forward().get_integer();
1955
1/9
✗ Branch 0 not taken.
✓ Branch 1 taken 12 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.
✗ Branch 8 not taken.
12 if ((unsigned int)num & 0xFF000000) throw_err_block(0, err_snes_address_doesnt_map_to_rom, hex((unsigned int)num, 6).data());
1956
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (num>realsnespos)
1957 {
1958 12 int end=snestopc(num);
1959 12 int start=snestopc(realsnespos);
1960 12 int len=end-start;
1961 12 add_addr_to_line(realsnespos & 0xFFFFFF);
1962
4/4
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 6 times.
72 for (int i=0;i<len;i++) write1(padbyte[i%12]);
1963 }
1964 12 }
1965
1966 90 void cmd_arch(const char* par) {
1967
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 45 times.
90 if(in_spcblock) throw_err_block(0, err_feature_unavaliable_in_spcblock);
1968
4/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 78 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 33 times.
90 if (!stricmp(par, "65816")) { arch=arch_65816; return; }
1969
4/4
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 12 times.
66 if (!stricmp(par, "spc700")) { arch=arch_spc700; return; }
1970
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
24 if (!stricmp(par, "superfx")) { arch=arch_superfx; return; }
1971 throw_err_block(0, err_broken_command, "arch", "Invalid architecture, expected one of 65816, spc700, superfx");
1972 }
1973
1974 72 void cmd_braces(const char* par) {
1975
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 36 times.
72 if(*par) throw_err_block(0, err_broken_command, "{ / }", "");
1976 72 }
1977
1978 template<void (*F)(const char*)>
1979 518 void wrap_mapper(const char* par) {
1980
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 259 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 146 times.
518 if(in_spcblock) throw_err_block(0, err_feature_unavaliable_in_spcblock);
1981
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
518 mapper_t previous_mapper = mapper;
1982 F(par);
1983
4/4
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 191 times.
✓ Branch 2 taken 101 times.
✓ Branch 3 taken 45 times.
518 if(!mapper_set){
1984 338 mapper_set = true;
1985
4/4
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 39 times.
✓ Branch 3 taken 6 times.
180 }else if(previous_mapper != mapper){
1986 156 throw_warning(1, warn_mapper_already_set);
1987 }
1988 518 }
1989
1990 template<mapper_t the_mapper>
1991 374 void mapper_simple(const char* par) {
1992
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
✓ Branch 2 taken 104 times.
374 if(*par) throw_err_block(0, err_invalid_mapper);
1993 374 mapper = the_mapper;
1994 374 }
1995
1996 45 void mapper_norom(const char* par) {
1997
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 27 times.
45 if(*par) throw_err_block(0, err_invalid_mapper);
1998 //$000000 would be the best snespos for this, but I don't care
1999 45 mapper = norom;
2000
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 21 times.
45 if(!force_checksum_fix)
2001 6 checksum_fix_enabled = false;//we don't know where the header is, so don't set the checksum
2002 45 }
2003
2004 27 void mapper_sa1rom(const char* par) {
2005
3/3
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 3 times.
27 if (*par) {
2006 // todo why doesn't this allow math?
2007
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
42 if (!is_digit(par[0]) || par[1]!=',' ||
2008
3/6
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
21 !is_digit(par[2]) || par[3]!=',' ||
2009
3/6
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
21 !is_digit(par[4]) || par[5]!=',' ||
2010
7/12
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 12 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 12 times.
42 !is_digit(par[6]) || par[7]) throw_err_block(0, err_invalid_mapper);
2011 /*
2012 // this part is just useless ???
2013 int len;
2014 string parbuf = par;
2015 autoptr<char**> pars=qpsplit(parbuf.raw(), ',', &len);
2016 verify_paren(pars);
2017 if (len!=4) throw_err_block(0, err_invalid_mapper); */
2018
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
21 sa1banks[0]=(par[0]-'0')<<20;
2019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
21 sa1banks[1]=(par[2]-'0')<<20;
2020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
21 sa1banks[4]=(par[4]-'0')<<20;
2021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
21 sa1banks[5]=(par[6]-'0')<<20;
2022 }
2023 else
2024 {
2025 6 sa1banks[0]=0<<20;
2026 6 sa1banks[1]=1<<20;
2027 6 sa1banks[4]=2<<20;
2028 6 sa1banks[5]=3<<20;
2029 }
2030 27 mapper=sa1rom;
2031 27 }
2032
2033 using command_fn_t = void(*)(const char*);
2034
2035 template<void (*F)(char**, int)>
2036 2822 void wrap_split(const char* par) {
2037
2/3
✓ Branch 0 taken 704 times.
✓ Branch 1 taken 707 times.
✗ Branch 2 not taken.
2822 string temp(par);
2038 1414 int num_words;
2039
2/3
✓ Branch 0 taken 704 times.
✓ Branch 1 taken 707 times.
✗ Branch 2 not taken.
2822 autoptr<char**> word = qsplit(temp.raw(), ' ', &num_words);
2040
8/8
✓ Branch 0 taken 1005 times.
✓ Branch 1 taken 406 times.
✓ Branch 2 taken 57 times.
✓ Branch 3 taken 444 times.
✓ Branch 4 taken 114 times.
✓ Branch 5 taken 1094 times.
✓ Branch 6 taken 57 times.
✓ Branch 7 taken 650 times.
2822 if(num_words == 1 && word[0][0] == 0) num_words--;
2041 F(word, num_words);
2042 4246 }
2043
2044 }
2045
2046
39/59
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 606 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 165 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 102 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 12 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 12 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 112 times.
✓ Branch 15 taken 2 times.
✓ Branch 16 taken 112 times.
✓ Branch 17 taken 2 times.
✓ Branch 18 taken 70 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 126 times.
✓ Branch 21 taken 6 times.
✓ Branch 22 taken 48 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 22 times.
✓ Branch 25 taken 44 times.
✓ Branch 26 taken 44 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 45 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 111 times.
✓ Branch 31 taken 198 times.
✓ Branch 32 taken 99 times.
✓ Branch 33 taken 494 times.
✓ Branch 34 taken 98 times.
✓ Branch 35 taken 12 times.
✓ Branch 36 taken 296 times.
✓ Branch 37 taken 8 times.
✓ Branch 38 taken 31 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 35 times.
✓ Branch 41 taken 19 times.
✓ Branch 42 taken 8 times.
✓ Branch 43 taken 420 times.
✓ Branch 44 taken 27 times.
✓ Branch 45 taken 807 times.
✓ Branch 46 taken 2020 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 3183 times.
✓ Branch 49 taken 1544 times.
✓ Branch 50 taken 758 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 2302 times.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
9828 static constexpr auto normal_commands = frozen::make_unordered_map<frozen::string, command_fn_t>({
2047 { "db", cmd_write_data<write1> },
2048 { "dw", cmd_write_data<write2> },
2049 { "dl", cmd_write_data<write3> },
2050 { "dd", cmd_write_data<write4> },
2051 { "assert", cmd_assert },
2052 { "undef", cmd_undef },
2053 { "error", cmd_error },
2054 { "warn", cmd_warn },
2055 { "warnings", wrap_split<cmd_warnings> },
2056 { "global", cmd_global },
2057 { "check", wrap_split<cmd_check> },
2058 { "asar", cmd_asar },
2059 { "include", cmd_include },
2060 { "includefrom", cmd_includefrom },
2061 { "includeonce", cmd_includeonce },
2062 { "org", cmd_org },
2063 { "struct", wrap_split<cmd_struct> },
2064 { "endstruct", wrap_split<cmd_endstruct> },
2065 { "spcblock", wrap_split<cmd_spcblock> },
2066 { "endspcblock", wrap_split<cmd_endspcblock> },
2067 { "base", cmd_base },
2068 { "dpbase", cmd_dpbase },
2069 { "optimize", wrap_split<cmd_optimize> },
2070 { "bank", cmd_bank },
2071 { "freespace", cmd_freespace<freespace_cmds::freespace> },
2072 { "freecode", cmd_freespace<freespace_cmds::freecode> },
2073 { "freedata", cmd_freespace<freespace_cmds::freedata> },
2074 { "segment", cmd_freespace<freespace_cmds::segment> },
2075 { "freespace_settings", cmd_freespace_settings },
2076 { "prot", cmd_prot },
2077 { "autoclean", wrap_split<cmd_autoclean> },
2078 { "freespacebyte", cmd_freespacebyte },
2079 { "pushpc", cmd_pushpc },
2080 { "pullpc", cmd_pullpc },
2081 { "pushbase", cmd_pushbase },
2082 { "pullbase", cmd_pullbase },
2083 { "pushns", cmd_pushns },
2084 { "pullns", cmd_pullns },
2085 { "namespace", wrap_split<cmd_namespace> },
2086 { "incsrc", cmd_incsrc },
2087 { "incbin", cmd_incbin },
2088 { "skip", wrap_split<cmd_skip_fill<false>> },
2089 { "fill", wrap_split<cmd_skip_fill<true>> },
2090 { "cleartable", cmd_cleartable },
2091 { "pushtable", cmd_pushtable },
2092 { "pulltable", cmd_pulltable },
2093 { "function", cmd_function },
2094 { "print", cmd_print },
2095 { "reset", cmd_reset },
2096 { "padbyte", cmd_padbytes<1, false> },
2097 { "padword", cmd_padbytes<2, false> },
2098 { "padlong", cmd_padbytes<3, false> },
2099 { "paddword", cmd_padbytes<4, false> },
2100 { "fillbyte", cmd_padbytes<1, true> },
2101 { "fillword", cmd_padbytes<2, true> },
2102 { "filllong", cmd_padbytes<3, true> },
2103 { "filldword", cmd_padbytes<4, true> },
2104 { "pad", cmd_pad },
2105 { "arch", cmd_arch },
2106 { "{", cmd_braces },
2107 { "}", cmd_braces },
2108
2109 { "lorom", wrap_mapper<mapper_simple<lorom>> },
2110 { "hirom", wrap_mapper<mapper_simple<hirom>> },
2111 { "exlorom", wrap_mapper<mapper_simple<exlorom>> },
2112 { "exhirom", wrap_mapper<mapper_simple<exhirom>> },
2113 { "sfxrom", wrap_mapper<mapper_simple<sfxrom>> },
2114 { "norom", wrap_mapper<mapper_norom> },
2115 { "sa1rom", wrap_mapper<mapper_sa1rom> },
2116 { "fullsa1rom", wrap_mapper<mapper_simple<bigsa1rom>> },
2117 });
2118
2119 namespace control_flow {
2120
2121 enum cf_cmds {
2122 c_if,
2123 c_elseif,
2124 c_while,
2125 c_for,
2126 };
2127
2128 // todo possibly this would be cleaner if `for` was refactored out entirely?
2129 template<cf_cmds type>
2130 6264 void cf_start(const char* par, int& single_line_for_tracker) {
2131 6264 const char* typ_name =
2132 type == c_if ? "if" :
2133 type == c_elseif ? "elseif" :
2134 type == c_while ? "while" : "for";
2135 6264 whiletracker wstatus;
2136
1/2
✓ Branch 0 taken 3132 times.
✗ Branch 1 not taken.
6264 wstatus.startline = get_current_line();
2137 6264 wstatus.iswhile = type == c_while;
2138 6264 wstatus.cond = false;
2139 6264 wstatus.is_for = false;
2140 6264 wstatus.for_start = wstatus.for_end = wstatus.for_cur = 0;
2141 6264 wstatus.for_has_var_backup = false;
2142 696 if(type == c_for) wstatus.is_for = true;
2143
2144 6264 bool is_for_cont = false;
2145 // if this is a for loop and a whilestatus entry already exists at this level,
2146 // and the for loop isn't finished, this is a continuation of the for loop
2147 696 if ((type == c_for)
2148
6/7
✓ Branch 0 taken 348 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 166 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 174 times.
✓ Branch 5 taken 166 times.
✓ Branch 6 taken 8 times.
696 && whilestatus.count > numif && whilestatus[numif].is_for
2149
11/14
✓ Branch 0 taken 348 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 332 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 166 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 289 times.
✓ Branch 7 taken 43 times.
✓ Branch 8 taken 123 times.
✓ Branch 9 taken 51 times.
✓ Branch 10 taken 123 times.
✓ Branch 11 taken 43 times.
✓ Branch 12 taken 123 times.
✓ Branch 13 taken 51 times.
1392 && whilestatus[numif].for_cur < whilestatus[numif].for_end) {
2150 492 is_for_cont = true;
2151 }
2152
6/9
✓ Branch 0 taken 246 times.
✓ Branch 1 taken 2886 times.
✓ Branch 2 taken 246 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2886 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1443 times.
✓ Branch 7 taken 1443 times.
✗ Branch 8 not taken.
6264 whiletracker& addedwstatus = is_for_cont ? whilestatus[numif] : (whilestatus[numif] = wstatus);
2153 //handle nested if statements
2154
4/4
✓ Branch 0 taken 336 times.
✓ Branch 1 taken 2796 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 174 times.
6264 if (numtrue!=numif && !(type == c_elseif && numtrue+1==numif))
2155 {
2156 228 if (type != c_elseif) numif++;
2157 324 return;
2158 }
2159 5376 if (type != c_elseif) numif++;
2160
2161 bool cond;
2162 if(type != c_for)
2163 {
2164
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1320 times.
✓ Branch 2 taken 1320 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
5280 if(!*par) throw_err_block(0, err_broken_command, typ_name, "Missing condition.");
2165
7/10
✓ Branch 0 taken 1320 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2619 times.
✓ Branch 3 taken 21 times.
✓ Branch 4 taken 1299 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1299 times.
✓ Branch 7 taken 21 times.
✓ Branch 8 taken 1299 times.
✗ Branch 9 not taken.
5406 cond = parse_math_expr(par)->evaluate_static().get_bool();
2166 }
2167
2168 if (type == c_for)
2169 {
2170
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 165 times.
✓ Branch 2 taken 165 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
660 if(!*par) throw_err_block(0, err_broken_for_loop, "missing loop range");
2171
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 165 times.
✓ Branch 2 taken 165 times.
660 if(single_line_for_tracker != 1)
2172 {
2173 numif--;
2174 throw_err_line(0, err_bad_single_line_for);
2175 }
2176
2177
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 246 times.
660 if(!is_for_cont)
2178 {
2179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
168 const char* past_eq = strchr(par, '=');
2180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
168 if(!past_eq)
2181 throw_err_block(0, err_broken_for_loop, "missing loop range");
2182
2183
2/3
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
168 string varname(par, past_eq - par);
2184 168 past_eq += 1;
2185
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
168 strip_whitespace(varname);
2186
2/4
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 84 times.
168 if(!validatedefinename(varname))
2187 throw_err_block(0, err_broken_for_loop, "invalid define name");
2188
2189
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
168 const char* range_sep = strqpstr(past_eq, "..");
2190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
168 if(!range_sep)
2191 throw_err_block(0, err_broken_for_loop, "invalid loop range");
2192
2193
2/3
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
168 string for_start(past_eq, range_sep - past_eq);
2194
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
168 strip_whitespace(for_start);
2195
2/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
168 string for_end(range_sep+2);
2196
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
168 strip_whitespace(for_end);
2197
2198
5/10
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 42 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 42 times.
✗ Branch 9 not taken.
168 addedwstatus.for_start = parse_math_expr(for_start)->evaluate_static().get_integer();
2199
5/10
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 42 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 42 times.
✗ Branch 9 not taken.
168 addedwstatus.for_end = parse_math_expr(for_end)->evaluate_static().get_integer();
2200
2201
2/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
168 addedwstatus.for_variable = varname;
2202 168 addedwstatus.for_cur = addedwstatus.for_start;
2203 168 }
2204 492 else addedwstatus.for_cur++;
2205
2206 660 addedwstatus.cond = addedwstatus.for_cur < addedwstatus.for_end;
2207 660 single_line_for_tracker = 2;
2208
5/5
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 165 times.
✓ Branch 3 taken 123 times.
✓ Branch 4 taken 42 times.
660 if(addedwstatus.cond)
2209 {
2210 492 numtrue++;
2211
6/8
✓ Branch 0 taken 123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 96 times.
✓ Branch 3 taken 27 times.
✓ Branch 4 taken 123 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 96 times.
✓ Branch 7 taken 27 times.
492 if(defines.exists(addedwstatus.for_variable))
2212 {
2213 384 addedwstatus.for_has_var_backup = true;
2214
4/7
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 96 times.
✓ Branch 3 taken 96 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 96 times.
✗ Branch 6 not taken.
384 addedwstatus.for_var_backup = defines.find(addedwstatus.for_variable);
2215 }
2216
3/7
✓ Branch 0 taken 123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 246 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 123 times.
✗ Branch 6 not taken.
492 defines.create(addedwstatus.for_variable) = ftostr(addedwstatus.for_cur);
2217 }
2218 }
2219 else if (type == c_if || type == c_while)
2220 {
2221 if(0);
2222
2/2
✓ Branch 0 taken 1884 times.
✓ Branch 1 taken 432 times.
4632 else if (cond)
2223 {
2224 3768 numtrue++;
2225
1/2
✓ Branch 0 taken 1884 times.
✗ Branch 1 not taken.
3768 elsestatus[numif]=true;
2226 }
2227
1/2
✓ Branch 0 taken 432 times.
✗ Branch 1 not taken.
864 else if (!cond)
2228 {
2229
1/2
✓ Branch 0 taken 432 times.
✗ Branch 1 not taken.
864 elsestatus[numif]=false;
2230 }
2231 4632 addedwstatus.cond = cond;
2232 }
2233 else if (type == c_elseif)
2234 {
2235
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 282 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
564 if (!numif) throw_err_block(1, err_misplaced_elseif);
2236
4/9
✓ Branch 0 taken 282 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 141 times.
✓ Branch 4 taken 141 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 141 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
564 if (whilestatus[numif - 1].iswhile) throw_err_block(1, err_elseif_in_while);
2237
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 174 times.
564 if (numif==numtrue) numtrue--;
2238
10/11
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 174 times.
✓ Branch 2 taken 108 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 39 times.
✓ Branch 5 taken 15 times.
✓ Branch 6 taken 93 times.
✓ Branch 7 taken 141 times.
✓ Branch 8 taken 15 times.
✓ Branch 9 taken 39 times.
✓ Branch 10 taken 102 times.
564 if (cond && !elsestatus[numif])
2239 {
2240 156 numtrue++;
2241
1/2
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
156 elsestatus[numif]=true;
2242 }
2243 }
2244
2/2
✓ Branch 0 taken 2928 times.
✓ Branch 1 taken 162 times.
6264 }
2245
2246 template<cf_cmds type>
2247 5604 void cf_end(const char* par, int& single_line_for_tracker) {
2248
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1401 times.
✓ Branch 2 taken 1401 times.
5604 if(*par) throw_err_block(0, err_broken_command, "end<...>", "");
2249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2802 times.
5604 if (!numif)
2250 throw_err_block(1, err_misplaced_endif);
2251 5604 whiletracker& thisws = whilestatus[numif - 1];
2252
2253
7/9
✓ Branch 0 taken 963 times.
✓ Branch 1 taken 174 times.
✓ Branch 2 taken 2100 times.
✓ Branch 3 taken 963 times.
✓ Branch 4 taken 174 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 963 times.
✓ Branch 7 taken 963 times.
✗ Branch 8 not taken.
5604 if((!thisws.is_for && !thisws.iswhile && type != c_if) ||
2254
5/5
✓ Branch 0 taken 264 times.
✓ Branch 1 taken 174 times.
✓ Branch 2 taken 438 times.
✓ Branch 3 taken 264 times.
✓ Branch 4 taken 174 times.
5604 (thisws.iswhile && type != c_while) ||
2255
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 1227 times.
✓ Branch 2 taken 1227 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1227 times.
4908 (thisws.is_for && type != c_for))
2256 throw_err_block(1, err_misplaced_endif);
2257
2258
2/2
✓ Branch 0 taken 2088 times.
✓ Branch 1 taken 714 times.
5604 if (numif==numtrue) numtrue--;
2259 5604 numif--;
2260
2261
5/5
✓ Branch 0 taken 174 times.
✓ Branch 1 taken 1227 times.
✓ Branch 2 taken 1401 times.
✓ Branch 3 taken 174 times.
✓ Branch 4 taken 1227 times.
5604 if(thisws.is_for)
2262 {
2263
3/3
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 174 times.
✓ Branch 2 taken 144 times.
696 if(single_line_for_tracker == 2) single_line_for_tracker = 3;
2264
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 348 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 174 times.
696 if(moreonline)
2265 {
2266 // sabotage the whilestatus to prevent the loop running again
2267 // and spamming more of the same error
2268 thisws.for_cur = thisws.for_end;
2269 thisws.cond = false;
2270 throw_err_block(0, err_bad_single_line_for);
2271 }
2272
2273
5/5
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 174 times.
✓ Branch 3 taken 123 times.
✓ Branch 4 taken 51 times.
696 if(thisws.cond)
2274 {
2275
5/5
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 123 times.
✓ Branch 3 taken 96 times.
✓ Branch 4 taken 27 times.
492 if(thisws.for_has_var_backup)
2276 384 defines.create(thisws.for_variable) = thisws.for_var_backup;
2277 else
2278 108 defines.remove(thisws.for_variable);
2279 }
2280 }
2281 5604 }
2282
2283 234 void cf_else(const char* par, int& single_line_for_tracker) {
2284
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 117 times.
✓ Branch 2 taken 117 times.
234 if(*par) throw_err_block(0, err_broken_command, "else", "");
2285
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 234 times.
234 if (!numif) throw_err_block(1, err_misplaced_else);
2286
7/13
✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 117 times.
✓ Branch 3 taken 234 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 117 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 117 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 117 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 117 times.
234 if (whilestatus[numif - 1].iswhile || whilestatus[numif - 1].is_for) throw_err_block(1, err_else_in_while_loop);
2287
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 162 times.
234 else if (numif==numtrue) numtrue--;
2288
9/9
✓ Branch 0 taken 150 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 45 times.
✓ Branch 4 taken 105 times.
✓ Branch 5 taken 81 times.
✓ Branch 6 taken 45 times.
✓ Branch 7 taken 30 times.
✓ Branch 8 taken 51 times.
162 else if (numif==numtrue+1 && !elsestatus[numif])
2289 {
2290 60 numtrue++;
2291 60 elsestatus[numif]=true;
2292 }
2293 234 }
2294
2295 }
2296
2297 static constexpr auto control_flow_commands = frozen::make_unordered_map<frozen::string, void(*)(const char*, int&)>({
2298 { "if", control_flow::cf_start<control_flow::c_if> },
2299 { "elseif", control_flow::cf_start<control_flow::c_elseif> },
2300 { "while", control_flow::cf_start<control_flow::c_while> },
2301 { "for", control_flow::cf_start<control_flow::c_for> },
2302 { "endif", control_flow::cf_end<control_flow::c_if> },
2303 { "endwhile", control_flow::cf_end<control_flow::c_while> },
2304 { "endfor", control_flow::cf_end<control_flow::c_for> },
2305 { "else", control_flow::cf_else },
2306 });
2307
2308 531 static void cmd_label_assign(const char* firstword, const char* params) {
2309
4/6
✓ Branch 0 taken 201 times.
✓ Branch 1 taken 264 times.
✓ Branch 2 taken 267 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 201 times.
✗ Branch 5 not taken.
531 if (firstword[0] == '\'' && firstword[1]) {
2310 201 int codepoint;
2311 402 const char* char_start = firstword + 1;
2312
1/2
✓ Branch 0 taken 402 times.
✗ Branch 1 not taken.
402 const char* after = char_start + utf8_val(&codepoint, char_start);
2313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 402 times.
402 if (codepoint == -1)
2314 throw_err_block(0, err_invalid_utf8);
2315
4/6
✓ Branch 0 taken 201 times.
✓ Branch 1 taken 201 times.
✓ Branch 2 taken 201 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 201 times.
✗ Branch 5 not taken.
402 if (after[0] == '\'' && after[1] == '\0') {
2316
8/14
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 396 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 198 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 396 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 198 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 198 times.
✗ Branch 13 not taken.
405 thetable.set_val(codepoint, parse_math_expr(params + 2)->evaluate_static().get_integer());
2317 396 return;
2318 } else {
2319 throw_err_block(0, err_invalid_character);
2320 }
2321 }
2322 129 const char* newlabelname = firstword;
2323 129 bool ismacro = false;
2324
2325
3/3
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 63 times.
✓ Branch 2 taken 63 times.
129 if (newlabelname[0] == '?') {
2326 6 ismacro = true;
2327 6 newlabelname++;
2328 }
2329
2330
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 123 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
129 if (ismacro && macrorecursion == 0) {
2331 throw_err_block(0, err_macro_label_outside_of_macro);
2332 }
2333
2334
3/4
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 63 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 66 times.
129 if (!confirmname(newlabelname))
2335 throw_err_block(0, err_invalid_label_name);
2336
2337 129 string completename;
2338
2339
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 123 times.
129 if (ismacro) {
2340
9/17
✓ Branch 0 taken 3 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 taken 3 times.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 3 times.
✗ Branch 16 not taken.
6 completename += STR ":macro_" + dec(calledmacros) + "_";
2341 }
2342
2343
1/2
✓ Branch 0 taken 129 times.
✗ Branch 1 not taken.
129 completename += newlabelname;
2344
2345
2/4
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
129 auto expr = parse_math_expr(params + 2);
2346
4/7
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 63 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 66 times.
✗ Branch 6 not taken.
129 int64_t num = expr->evaluate_non_forward().get_integer();
2347
2/4
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
129 bool is_static = expr->has_label() <= 1;
2348
2349
1/9
✗ Branch 0 not taken.
✓ Branch 1 taken 129 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.
✗ Branch 8 not taken.
129 if (num&~0xFFFFFF) throw_err_block(1, err_snes_address_out_of_bounds, hex(num, 6).data());
2350
2351
4/6
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 63 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 66 times.
✗ Branch 5 not taken.
129 setlabel(ns + completename, num, is_static);
2352 129 }
2353
2354 // single_line_for_tracker is:
2355 // 0 if not in first block of line, not in (single-line) for loop
2356 // 1 if first block of line
2357 // 2 if in single-line for loop
2358 // 3 if after endfor (of a single-line loop)
2359 58702 void assembleblock(const char *block, int &single_line_for_tracker) {
2360 // don't do this here; assembleline already did it for us
2361 // callstack_push cs_push(callstack_entry_type::BLOCK, block);
2362
3/3
✓ Branch 0 taken 9010 times.
✓ Branch 1 taken 29249 times.
✓ Branch 2 taken 20443 times.
58702 if (!*block) return;
2363
2364 // assumption: if the first word of a line contains quotes/spaces, it's going
2365 // to be invalid anyways. well, except for character assignment......
2366 40628 string firstword;
2367 40628 const char *params = block;
2368
1/2
✓ Branch 0 taken 40628 times.
✗ Branch 1 not taken.
40628 grab_until_space(firstword, params);
2369
2370 // when writing out the data for the addrToLine mapping,
2371 // we want to write out the snespos we had before writing opcodes
2372 40628 int addrToLinePos = realsnespos & 0xFFFFFF;
2373
2374
2/3
✓ Branch 0 taken 20185 times.
✓ Branch 1 taken 20443 times.
✗ Branch 2 not taken.
40628 string firstword_lower = firstword;
2375 40628 lower(firstword_lower);
2376
2377
5/7
✓ Branch 0 taken 20185 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23527 times.
✓ Branch 3 taken 17101 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3084 times.
✓ Branch 6 taken 17359 times.
40628 if (auto it = control_flow_commands.find(frozen::string(firstword_lower.data(), firstword_lower.length())); it != control_flow_commands.end()) {
2378
4/4
✓ Branch 0 taken 3063 times.
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 3063 times.
✓ Branch 3 taken 21 times.
6168 return it->second(params, single_line_for_tracker);
2379
2/2
✓ Branch 0 taken 1770 times.
✓ Branch 1 taken 32690 times.
34460 } else if (numif != numtrue) {
2380 1770 return;
2381 }
2382
2383 32690 bool addlabeled = false;
2384 // while first word is non-empty,
2385 // and rest {is empty or doesn't start with " = "},
2386 // try to run addlabel
2387 32972 while (firstword[0]
2388
8/8
✓ Branch 0 taken 14554 times.
✓ Branch 1 taken 16570 times.
✓ Branch 2 taken 15295 times.
✓ Branch 3 taken 1107 times.
✓ Branch 4 taken 26819 times.
✓ Branch 5 taken 1398 times.
✓ Branch 6 taken 13369 times.
✓ Branch 7 taken 267 times.
32972 && !(params[0] && params[1] && stribegin(params, "= "))
2389
7/8
✓ Branch 0 taken 32972 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32395 times.
✓ Branch 3 taken 46 times.
✓ Branch 4 taken 1049 times.
✓ Branch 5 taken 31346 times.
✓ Branch 6 taken 1049 times.
✓ Branch 7 taken 31877 times.
65944 && addlabel(firstword)) {
2390 // addlabel was ok, move to the next word
2391 1049 addlabeled = true;
2392 // if there's no next word, we're done here
2393
3/3
✓ Branch 0 taken 376 times.
✓ Branch 1 taken 529 times.
✓ Branch 2 taken 144 times.
1049 if (!*params) return;
2394 // otherwise pull next word into firstword
2395
1/2
✓ Branch 0 taken 282 times.
✗ Branch 1 not taken.
282 grab_until_space(firstword, params);
2396 }
2397
2398
1/2
✓ Branch 0 taken 31877 times.
✗ Branch 1 not taken.
31877 firstword_lower = firstword;
2399 31877 lower(firstword_lower);
2400
2401 // recheck for any of the conditionals tested above
2402
10/15
✓ Branch 0 taken 282 times.
✓ Branch 1 taken 31595 times.
✓ Branch 2 taken 138 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 144 times.
✓ Branch 5 taken 138 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 15817 times.
✓ Branch 8 taken 144 times.
✓ Branch 9 taken 144 times.
✓ Branch 10 taken 15916 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 16060 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
31877 if (addlabeled && control_flow_commands.find(frozen::string(firstword_lower.data(), firstword_lower.length())) != control_flow_commands.end()) {
2403 throw_err_block(0, err_label_before_if, firstword.data());
2404 }
2405
2406
4/4
✓ Branch 0 taken 31857 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 10105 times.
✓ Branch 3 taken 21752 times.
31877 if (asblock_pick(firstword_lower, params)) {
2407
1/2
✓ Branch 0 taken 10105 times.
✗ Branch 1 not taken.
10105 add_addr_to_line(addrToLinePos);
2408 10105 return;
2409 }
2410
2411
3/3
✓ Branch 0 taken 261 times.
✓ Branch 1 taken 10762 times.
✓ Branch 2 taken 10729 times.
21752 if (firstword[0] == '%') {
2412 // imo using strchr here is jank, but it works i guess
2413 // (labels can't contain %)
2414
4/5
✓ Branch 0 taken 255 times.
✓ Branch 1 taken 267 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 255 times.
✓ Branch 4 taken 6 times.
522 return callmacro(strchr(block, '%') + 1);
2415 }
2416
2417
5/7
✓ Branch 0 taken 10501 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20960 times.
✓ Branch 3 taken 270 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10453 times.
✓ Branch 6 taken 276 times.
21230 if (auto it = normal_commands.find(frozen::string(firstword_lower.data(), firstword_lower.length())); it != normal_commands.end()) {
2418
4/4
✓ Branch 0 taken 5148 times.
✓ Branch 1 taken 5083 times.
✓ Branch 2 taken 5367 times.
✓ Branch 3 taken 5086 times.
20684 return it->second(params);
2419 }
2420
2421
4/4
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 525 times.
✓ Branch 3 taken 6 times.
546 if (stribegin(params, "= ")) return cmd_label_assign(firstword, params);
2422
2423
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 throw_err_block(1, err_unknown_command);
2424 50938 }
2425