LCOV - code coverage report
Current view: top level - asar - main.cpp (source / functions) Coverage Total Hit
Test: asar.info Lines: 83.4 % 465 388
Test Date: 2024-01-15 16:23:49 Functions: 81.8 % 22 18
Branches: 66.4 % 491 326

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

Generated by: LCOV version 2.0-1