2016-02-11 22:54:43 +01:00
|
|
|
/** @file
|
|
|
|
|
*
|
|
|
|
|
* @par History
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
2018-01-29 21:55:48 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
|
|
#include "../clib/clib.h"
|
|
|
|
|
#include "../clib/logfacility.h"
|
|
|
|
|
#include "../clib/passert.h"
|
|
|
|
|
#include "../clib/rawtypes.h"
|
|
|
|
|
#include "../clib/stlutil.h"
|
|
|
|
|
#include "compctx.h"
|
2016-02-11 22:54:43 +01:00
|
|
|
// EPROG compiler-only functions
|
|
|
|
|
#include "eprog.h"
|
|
|
|
|
#include "filefmt.h"
|
2018-01-01 21:49:30 +01:00
|
|
|
#include "fmodule.h"
|
2018-01-29 21:55:48 +01:00
|
|
|
#include "symcont.h"
|
|
|
|
|
#include "token.h"
|
|
|
|
|
#include "tokens.h"
|
2016-02-11 22:54:43 +01:00
|
|
|
#include "userfunc.h"
|
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
namespace Pol
|
|
|
|
|
{
|
|
|
|
|
namespace Bscript
|
|
|
|
|
{
|
|
|
|
|
extern int include_debug;
|
|
|
|
|
|
|
|
|
|
void EScriptProgram::erase()
|
|
|
|
|
{
|
|
|
|
|
tokens.erase();
|
|
|
|
|
symbols.erase();
|
|
|
|
|
nglobals = 0;
|
|
|
|
|
dbg_filenum.clear();
|
|
|
|
|
dbg_linenum.clear();
|
|
|
|
|
globalvarnames.clear();
|
|
|
|
|
blocks.clear();
|
|
|
|
|
dbg_functions.clear();
|
|
|
|
|
dbg_ins_blocks.clear();
|
|
|
|
|
dbg_ins_statementbegin.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EScriptProgram::update_dbg_pos( const Token& token )
|
|
|
|
|
{
|
|
|
|
|
if ( token.dbg_filenum != 0 )
|
|
|
|
|
{
|
|
|
|
|
curfile = token.dbg_filenum;
|
|
|
|
|
curline = token.dbg_linenum;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EScriptProgram::add_ins_dbg_info()
|
|
|
|
|
{
|
|
|
|
|
dbg_filenum.push_back( curfile );
|
|
|
|
|
dbg_linenum.push_back( curline );
|
|
|
|
|
dbg_ins_blocks.push_back( curblock );
|
|
|
|
|
dbg_ins_statementbegin.push_back( statementbegin );
|
|
|
|
|
statementbegin = false;
|
|
|
|
|
passert( tokens.count() == dbg_filenum.size() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EScriptProgram::setcontext( const CompilerContext& ctx )
|
|
|
|
|
{
|
|
|
|
|
curfile = ctx.dbg_filenum;
|
|
|
|
|
curline = ctx.line;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EScriptProgram::append( const StoredToken& stoken )
|
|
|
|
|
{
|
2018-10-09 16:36:35 +02:00
|
|
|
tokens.append_tok( stoken, nullptr );
|
2016-02-19 19:26:35 +01:00
|
|
|
|
|
|
|
|
add_ins_dbg_info();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EScriptProgram::append( const StoredToken& stoken, unsigned* posn )
|
|
|
|
|
{
|
|
|
|
|
tokens.append_tok( stoken, posn );
|
|
|
|
|
|
|
|
|
|
add_ins_dbg_info();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EScriptProgram::append( const StoredToken& stoken, const CompilerContext& ctx )
|
|
|
|
|
{
|
2018-10-09 16:36:35 +02:00
|
|
|
tokens.append_tok( stoken, nullptr );
|
2016-02-19 19:26:35 +01:00
|
|
|
|
|
|
|
|
setcontext( ctx );
|
|
|
|
|
|
|
|
|
|
add_ins_dbg_info();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EScriptProgram::append( const StoredToken& stoken, const CompilerContext& ctx, unsigned* posn )
|
|
|
|
|
{
|
|
|
|
|
tokens.append_tok( stoken, posn );
|
|
|
|
|
|
|
|
|
|
setcontext( ctx );
|
|
|
|
|
|
|
|
|
|
add_ins_dbg_info();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EScriptProgram::addToken( const Token& token )
|
|
|
|
|
{
|
|
|
|
|
unsigned tokpos = 0;
|
|
|
|
|
if ( token.id > 255 )
|
|
|
|
|
{
|
|
|
|
|
throw std::runtime_error( "Trying to write an illegal token" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
update_dbg_pos( token );
|
|
|
|
|
|
|
|
|
|
switch ( token.type )
|
|
|
|
|
{
|
|
|
|
|
case TYP_OPERAND: // is variable name, long, double, string lit
|
|
|
|
|
{
|
|
|
|
|
unsigned sympos = 0;
|
2018-02-03 19:05:22 +01:00
|
|
|
BTokenType type = token.type;
|
2016-02-19 19:26:35 +01:00
|
|
|
switch ( token.id )
|
|
|
|
|
{
|
|
|
|
|
case TOK_LONG:
|
|
|
|
|
symbols.append( token.lval, sympos );
|
|
|
|
|
break;
|
|
|
|
|
case TOK_DOUBLE:
|
|
|
|
|
symbols.append( token.dval, sympos );
|
|
|
|
|
break;
|
|
|
|
|
case TOK_STRING: // string literal
|
|
|
|
|
symbols.append( token.tokval(), sympos );
|
|
|
|
|
break;
|
|
|
|
|
case INS_ADDMEMBER2:
|
|
|
|
|
case INS_ADDMEMBER_ASSIGN:
|
|
|
|
|
case TOK_IDENT: // unclassified (ick)
|
|
|
|
|
symbols.append( token.tokval(), sympos );
|
|
|
|
|
break;
|
|
|
|
|
case TOK_GLOBALVAR:
|
|
|
|
|
case TOK_LOCALVAR:
|
|
|
|
|
sympos = token.lval;
|
|
|
|
|
break;
|
2018-02-03 19:05:22 +01:00
|
|
|
case TOK_FUNCREF:
|
|
|
|
|
// num params in type
|
|
|
|
|
type = static_cast<BTokenType>( token.userfunc->parameters.size() );
|
2016-02-19 19:26:35 +01:00
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2018-02-03 19:05:22 +01:00
|
|
|
tokens.append_tok( StoredToken( token.module, token.id, type, sympos ), &tokpos );
|
|
|
|
|
if ( token.id == TOK_FUNCREF )
|
|
|
|
|
token.userfunc->forward_callers.push_back( tokpos );
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case TYP_METHOD:
|
|
|
|
|
{
|
|
|
|
|
if ( token.id != INS_CALL_METHOD_ID )
|
|
|
|
|
{
|
|
|
|
|
unsigned sympos = 0;
|
|
|
|
|
passert( token.tokval() );
|
|
|
|
|
|
|
|
|
|
symbols.append( token.tokval(), sympos );
|
|
|
|
|
|
|
|
|
|
tokens.append_tok(
|
|
|
|
|
StoredToken(
|
|
|
|
|
token.module, token.id,
|
|
|
|
|
static_cast<BTokenType>(
|
|
|
|
|
token.lval ), // # of params, stored in Token.lval, saved in StoredToken.type
|
|
|
|
|
sympos ),
|
|
|
|
|
&tokpos );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
tokens.append_tok( StoredToken( token.module, token.id, static_cast<BTokenType>( token.lval ),
|
|
|
|
|
static_cast<unsigned>( token.dval ) ),
|
|
|
|
|
&tokpos );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case TYP_FUNC:
|
|
|
|
|
{
|
|
|
|
|
unsigned sympos = 0;
|
|
|
|
|
if ( include_debug )
|
|
|
|
|
{
|
|
|
|
|
if ( token.tokval() )
|
|
|
|
|
symbols.append( token.tokval(), sympos );
|
|
|
|
|
}
|
|
|
|
|
tokens.append_tok(
|
|
|
|
|
StoredToken(
|
|
|
|
|
token.module, token.id,
|
|
|
|
|
static_cast<BTokenType>(
|
|
|
|
|
token.lval ), // function index, stored in Token.lval, saved in StoredToken.type
|
|
|
|
|
sympos ),
|
|
|
|
|
&tokpos );
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case TYP_RESERVED:
|
|
|
|
|
case TYP_OPERATOR:
|
|
|
|
|
case TYP_UNARY_OPERATOR:
|
|
|
|
|
if ( token.id == TOK_ARRAY_SUBSCRIPT )
|
|
|
|
|
{
|
|
|
|
|
// array subscript operators store their
|
|
|
|
|
// array index number in offset
|
|
|
|
|
tokens.append_tok( StoredToken( token.module, token.id, token.type, token.lval ) );
|
|
|
|
|
}
|
|
|
|
|
else if ( token.id == INS_GET_MEMBER || token.id == INS_SET_MEMBER ||
|
|
|
|
|
token.id == INS_SET_MEMBER_CONSUME )
|
|
|
|
|
{
|
|
|
|
|
unsigned sympos = 0;
|
|
|
|
|
symbols.append( token.tokval(), sympos );
|
|
|
|
|
tokens.append_tok( StoredToken( token.module, token.id, token.type, sympos ), &tokpos );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
tokens.append_tok( StoredToken( token.module, token.id, token.type, token.lval ), &tokpos );
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case TYP_CONTROL:
|
|
|
|
|
switch ( token.id )
|
|
|
|
|
{
|
|
|
|
|
case CTRL_MAKELOCAL:
|
|
|
|
|
tokens.append_tok( StoredToken( token.module, token.id, token.type ) );
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case CTRL_JSR_USERFUNC:
|
|
|
|
|
tokens.append_tok( StoredToken( token.module, token.id, token.type, 0 ), &tokpos );
|
|
|
|
|
token.userfunc->forward_callers.push_back( tokpos );
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case INS_POP_PARAM_BYREF:
|
|
|
|
|
case INS_POP_PARAM:
|
|
|
|
|
{
|
|
|
|
|
unsigned sympos = 0;
|
|
|
|
|
symbols.append( token.tokval(), sympos );
|
|
|
|
|
tokens.append_tok( StoredToken( token.module, token.id, token.type, sympos ) );
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2020-04-23 19:12:04 -07:00
|
|
|
case INS_SKIPIFTRUE_ELSE_CONSUME:
|
|
|
|
|
{
|
|
|
|
|
unsigned sympos = token.lval;
|
|
|
|
|
tokens.append_tok( StoredToken( token.module, token.id, token.type, sympos ) );
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
default:
|
|
|
|
|
ERROR_PRINT << "AddToken: Can't handle TYP_CONTROL: " << token << "\n";
|
|
|
|
|
throw std::runtime_error( "Unexpected token in AddToken() (1)" );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ERROR_PRINT << "AddToken: Can't handle " << token << "\n";
|
|
|
|
|
throw std::runtime_error( "Unexpected Token passed to AddToken() (2)" );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
add_ins_dbg_info();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int EScriptProgram::write( const char* fname )
|
|
|
|
|
{
|
|
|
|
|
EScriptProgram& program = *this;
|
|
|
|
|
FILE* fp = fopen( fname, "wb" );
|
|
|
|
|
if ( !fp )
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
BSCRIPT_FILE_HDR hdr;
|
|
|
|
|
hdr.magic2[0] = BSCRIPT_FILE_MAGIC0;
|
|
|
|
|
hdr.magic2[1] = BSCRIPT_FILE_MAGIC1;
|
|
|
|
|
hdr.version = ESCRIPT_FILE_VER_CURRENT; // auto-set to latest version (see filefmt.h)
|
|
|
|
|
hdr.globals = static_cast<unsigned short>( globalvarnames.size() );
|
|
|
|
|
fwrite( &hdr, sizeof hdr, 1, fp );
|
|
|
|
|
|
|
|
|
|
BSCRIPT_SECTION_HDR sechdr;
|
|
|
|
|
|
|
|
|
|
if ( haveProgram )
|
|
|
|
|
{
|
|
|
|
|
BSCRIPT_PROGDEF_HDR progdef_hdr;
|
|
|
|
|
memset( &progdef_hdr, 0, sizeof progdef_hdr );
|
|
|
|
|
sechdr.type = BSCRIPT_SECTION_PROGDEF;
|
|
|
|
|
sechdr.length = sizeof progdef_hdr;
|
|
|
|
|
fwrite( &sechdr, sizeof sechdr, 1, fp );
|
|
|
|
|
progdef_hdr.expectedArgs = expectedArgs;
|
|
|
|
|
fwrite( &progdef_hdr, sizeof progdef_hdr, 1, fp );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for ( auto& module : program.modules )
|
|
|
|
|
{
|
|
|
|
|
sechdr.type = BSCRIPT_SECTION_MODULE;
|
|
|
|
|
sechdr.length = 0;
|
|
|
|
|
fwrite( &sechdr, sizeof sechdr, 1, fp );
|
|
|
|
|
|
|
|
|
|
BSCRIPT_MODULE_HDR modhdr;
|
|
|
|
|
memset( &modhdr, 0, sizeof modhdr );
|
2019-08-25 09:05:15 +02:00
|
|
|
Clib::stracpy( modhdr.modulename, module->modulename.get().c_str(), sizeof modhdr.modulename );
|
2016-02-19 19:26:35 +01:00
|
|
|
modhdr.nfuncs = static_cast<unsigned int>( module->used_functions.size() );
|
|
|
|
|
fwrite( &modhdr, sizeof modhdr, 1, fp );
|
|
|
|
|
for ( auto& module_func : module->used_functions )
|
|
|
|
|
{
|
|
|
|
|
BSCRIPT_MODULE_FUNCTION func;
|
|
|
|
|
memset( &func, 0, sizeof func );
|
|
|
|
|
passert( module_func->used );
|
|
|
|
|
|
2019-08-25 09:05:15 +02:00
|
|
|
Clib::stracpy( func.funcname, module_func->name.get().c_str(), sizeof func.funcname );
|
2016-02-19 19:26:35 +01:00
|
|
|
func.nargs = static_cast<unsigned char>( module_func->nargs );
|
|
|
|
|
|
|
|
|
|
fwrite( &func, sizeof func, 1, fp );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sechdr.type = BSCRIPT_SECTION_CODE;
|
|
|
|
|
sechdr.length = program.tokens.get_write_length();
|
|
|
|
|
fwrite( &sechdr, sizeof sechdr, 1, fp );
|
|
|
|
|
program.tokens.write( fp );
|
|
|
|
|
|
|
|
|
|
sechdr.type = BSCRIPT_SECTION_SYMBOLS;
|
|
|
|
|
sechdr.length = program.symbols.get_write_length();
|
|
|
|
|
fwrite( &sechdr, sizeof sechdr, 1, fp );
|
|
|
|
|
program.symbols.write( fp );
|
|
|
|
|
|
|
|
|
|
if ( !exported_functions.empty() )
|
|
|
|
|
{
|
|
|
|
|
BSCRIPT_EXPORTED_FUNCTION bef;
|
|
|
|
|
sechdr.type = BSCRIPT_SECTION_EXPORTED_FUNCTIONS;
|
|
|
|
|
sechdr.length = static_cast<unsigned int>( exported_functions.size() * sizeof bef );
|
|
|
|
|
fwrite( &sechdr, sizeof sechdr, 1, fp );
|
|
|
|
|
for ( auto& elem : exported_functions )
|
|
|
|
|
{
|
2019-08-25 09:05:15 +02:00
|
|
|
Clib::stracpy( bef.funcname, elem.name.c_str(), sizeof bef.funcname );
|
2016-02-19 19:26:35 +01:00
|
|
|
bef.nargs = elem.nargs;
|
|
|
|
|
bef.PC = elem.PC;
|
|
|
|
|
fwrite( &bef, sizeof bef, 1, fp );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fclose( fp );
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EScriptProgramCheckpoint::EScriptProgramCheckpoint( const EScriptProgram& prog )
|
|
|
|
|
{
|
|
|
|
|
commit( prog );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EScriptProgramCheckpoint::commit( const EScriptProgram& prog )
|
|
|
|
|
{
|
|
|
|
|
module_count = static_cast<unsigned int>( prog.modules.size() );
|
|
|
|
|
tokens_count = prog.tokens.count();
|
|
|
|
|
symbols_length = prog.symbols.length();
|
|
|
|
|
sourcelines_count = static_cast<unsigned int>( prog.sourcelines.size() );
|
|
|
|
|
fileline_count = static_cast<unsigned int>( prog.fileline.size() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned EScriptProgram::varcount( unsigned block )
|
|
|
|
|
{
|
|
|
|
|
unsigned cnt = static_cast<unsigned int>( blocks[block].localvarnames.size() );
|
|
|
|
|
if ( block != 0 )
|
|
|
|
|
{
|
|
|
|
|
cnt += varcount( blocks[block].parentblockidx );
|
|
|
|
|
}
|
|
|
|
|
return cnt;
|
|
|
|
|
}
|
|
|
|
|
unsigned EScriptProgram::parentvariables( unsigned parent )
|
|
|
|
|
{
|
|
|
|
|
unsigned cnt = 0;
|
|
|
|
|
if ( parent != 0 )
|
|
|
|
|
{
|
|
|
|
|
cnt = blocks[parent].parentvariables + parentvariables( blocks[parent].parentblockidx );
|
|
|
|
|
}
|
|
|
|
|
return cnt;
|
|
|
|
|
}
|
|
|
|
|
int EScriptProgram::write_dbg( const char* fname, bool gen_txt )
|
|
|
|
|
{
|
|
|
|
|
FILE* fp = fopen( fname, "wb" );
|
|
|
|
|
if ( !fp )
|
|
|
|
|
return -1;
|
|
|
|
|
|
2018-10-09 16:36:35 +02:00
|
|
|
FILE* fptext = nullptr;
|
2016-02-19 19:26:35 +01:00
|
|
|
if ( gen_txt )
|
|
|
|
|
fptext = fopen( ( std::string( fname ) + ".txt" ).c_str(), "wt" );
|
|
|
|
|
|
|
|
|
|
u32 count;
|
|
|
|
|
|
|
|
|
|
// just a version number
|
|
|
|
|
count = 3;
|
|
|
|
|
fwrite( &count, sizeof count, 1, fp );
|
|
|
|
|
|
|
|
|
|
count = static_cast<unsigned int>( dbg_filenames.size() );
|
|
|
|
|
fwrite( &count, sizeof count, 1, fp );
|
|
|
|
|
for ( unsigned i = 0; i < dbg_filenames.size(); ++i )
|
|
|
|
|
{
|
|
|
|
|
if ( fptext )
|
|
|
|
|
fprintf( fptext, "File %u: %s\n", i, dbg_filenames[i].c_str() );
|
|
|
|
|
count = static_cast<unsigned int>( dbg_filenames[i].size() + 1 );
|
|
|
|
|
fwrite( &count, sizeof count, 1, fp );
|
|
|
|
|
fwrite( dbg_filenames[i].c_str(), count, 1, fp );
|
|
|
|
|
}
|
|
|
|
|
count = static_cast<unsigned int>( globalvarnames.size() );
|
|
|
|
|
fwrite( &count, sizeof count, 1, fp );
|
|
|
|
|
for ( unsigned i = 0; i < globalvarnames.size(); ++i )
|
|
|
|
|
{
|
|
|
|
|
if ( fptext )
|
|
|
|
|
fprintf( fptext, "Global %u: %s\n", i, globalvarnames[i].c_str() );
|
|
|
|
|
count = static_cast<unsigned int>( globalvarnames[i].size() + 1 );
|
|
|
|
|
fwrite( &count, sizeof count, 1, fp );
|
|
|
|
|
fwrite( globalvarnames[i].c_str(), count, 1, fp );
|
|
|
|
|
}
|
|
|
|
|
count = tokens.count();
|
|
|
|
|
fwrite( &count, sizeof count, 1, fp );
|
|
|
|
|
for ( unsigned i = 0; i < tokens.count(); ++i )
|
|
|
|
|
{
|
|
|
|
|
if ( fptext )
|
|
|
|
|
fprintf( fptext, "Ins %u: File %u, Line %u, Block %u %s\n", i, dbg_filenum[i], dbg_linenum[i],
|
|
|
|
|
dbg_ins_blocks[i], ( dbg_ins_statementbegin[i] ? "StatementBegin" : "" ) );
|
|
|
|
|
BSCRIPT_DBG_INSTRUCTION ins;
|
|
|
|
|
ins.filenum = dbg_filenum[i];
|
|
|
|
|
ins.linenum = dbg_linenum[i];
|
|
|
|
|
ins.blocknum = dbg_ins_blocks[i];
|
|
|
|
|
ins.statementbegin = dbg_ins_statementbegin[i] ? 1 : 0;
|
|
|
|
|
ins.rfu1 = 0;
|
|
|
|
|
ins.rfu2 = 0;
|
|
|
|
|
fwrite( &ins, sizeof ins, 1, fp );
|
|
|
|
|
}
|
|
|
|
|
count = static_cast<unsigned int>( blocks.size() );
|
|
|
|
|
fwrite( &count, sizeof count, 1, fp );
|
|
|
|
|
for ( unsigned i = 0; i < blocks.size(); ++i )
|
|
|
|
|
{
|
|
|
|
|
const EPDbgBlock& block = blocks[i];
|
|
|
|
|
if ( fptext )
|
|
|
|
|
{
|
|
|
|
|
fprintf( fptext, "Block %u:\n", i );
|
|
|
|
|
fprintf( fptext, " Parent block: %u\n", block.parentblockidx );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u32 tmp;
|
|
|
|
|
tmp = block.parentblockidx;
|
|
|
|
|
fwrite( &tmp, sizeof tmp, 1, fp );
|
|
|
|
|
tmp = block.parentvariables;
|
|
|
|
|
fwrite( &tmp, sizeof tmp, 1, fp );
|
|
|
|
|
|
|
|
|
|
count = static_cast<unsigned int>( block.localvarnames.size() );
|
|
|
|
|
fwrite( &count, sizeof count, 1, fp );
|
|
|
|
|
|
|
|
|
|
unsigned int varfirst = block.parentvariables;
|
|
|
|
|
unsigned int varlast = static_cast<unsigned int>( varfirst + block.localvarnames.size() - 1 );
|
|
|
|
|
if ( varlast >= varfirst )
|
|
|
|
|
{
|
|
|
|
|
if ( fptext )
|
|
|
|
|
fprintf( fptext, " Local variables %u-%u: \n", varfirst, varlast );
|
|
|
|
|
for ( unsigned j = 0; j < block.localvarnames.size(); ++j )
|
|
|
|
|
{
|
|
|
|
|
std::string varname = block.localvarnames[j];
|
|
|
|
|
if ( fptext )
|
|
|
|
|
fprintf( fptext, " %u: %s\n", varfirst + j, varname.c_str() );
|
|
|
|
|
|
|
|
|
|
count = static_cast<unsigned int>( varname.size() + 1 );
|
|
|
|
|
fwrite( &count, sizeof count, 1, fp );
|
|
|
|
|
fwrite( varname.c_str(), count, 1, fp );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
count = static_cast<unsigned int>( dbg_functions.size() );
|
|
|
|
|
fwrite( &count, sizeof count, 1, fp );
|
|
|
|
|
for ( unsigned i = 0; i < dbg_functions.size(); ++i )
|
|
|
|
|
{
|
|
|
|
|
const EPDbgFunction& func = dbg_functions[i];
|
|
|
|
|
if ( fptext )
|
|
|
|
|
{
|
|
|
|
|
fprintf( fptext, "Function %u: %s\n", i, func.name.c_str() );
|
|
|
|
|
fprintf( fptext, " FirstPC=%u, lastPC=%u\n", func.firstPC, func.lastPC );
|
|
|
|
|
}
|
|
|
|
|
count = static_cast<unsigned int>( func.name.size() + 1 );
|
|
|
|
|
fwrite( &count, sizeof count, 1, fp );
|
|
|
|
|
fwrite( func.name.c_str(), count, 1, fp );
|
|
|
|
|
u32 tmp;
|
|
|
|
|
tmp = func.firstPC;
|
|
|
|
|
fwrite( &tmp, sizeof tmp, 1, fp );
|
|
|
|
|
tmp = func.lastPC;
|
|
|
|
|
fwrite( &tmp, sizeof tmp, 1, fp );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( fptext )
|
|
|
|
|
fclose( fptext );
|
2018-10-09 16:36:35 +02:00
|
|
|
fptext = nullptr;
|
2016-02-19 19:26:35 +01:00
|
|
|
fclose( fp );
|
2018-10-09 16:36:35 +02:00
|
|
|
fp = nullptr;
|
2016-02-19 19:26:35 +01:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int EScriptProgram::add_dbg_filename( const std::string& filename )
|
|
|
|
|
{
|
|
|
|
|
for ( unsigned i = 0; i < dbg_filenames.size(); ++i )
|
|
|
|
|
{
|
|
|
|
|
if ( dbg_filenames[i] == filename )
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// file 0 is nothing
|
|
|
|
|
if ( dbg_filenames.empty() )
|
|
|
|
|
dbg_filenames.push_back( "" );
|
|
|
|
|
|
|
|
|
|
dbg_filenames.push_back( filename );
|
|
|
|
|
return static_cast<int>( dbg_filenames.size() - 1 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string EScriptProgram::dbg_get_instruction( size_t atPC ) const
|
|
|
|
|
{
|
|
|
|
|
OSTRINGSTREAM os;
|
|
|
|
|
os << instr[atPC].token;
|
|
|
|
|
return OSTRINGSTREAM_STR( os );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void EScriptProgram::setstatementbegin()
|
|
|
|
|
{
|
|
|
|
|
statementbegin = true;
|
|
|
|
|
}
|
|
|
|
|
void EScriptProgram::enterfunction()
|
|
|
|
|
{
|
|
|
|
|
savecurblock = curblock;
|
|
|
|
|
curblock = 0;
|
|
|
|
|
}
|
|
|
|
|
void EScriptProgram::leavefunction()
|
|
|
|
|
{
|
|
|
|
|
curblock = savecurblock;
|
|
|
|
|
}
|
|
|
|
|
void EScriptProgram::enterblock()
|
|
|
|
|
{
|
|
|
|
|
EPDbgBlock block;
|
|
|
|
|
if ( blocks.empty() )
|
|
|
|
|
{
|
|
|
|
|
block.parentblockidx = 0;
|
|
|
|
|
block.parentvariables = 0;
|
|
|
|
|
blocks.push_back( block );
|
|
|
|
|
curblock = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
block.parentblockidx = curblock;
|
|
|
|
|
block.parentvariables = varcount( curblock );
|
|
|
|
|
|
|
|
|
|
curblock = static_cast<unsigned int>( blocks.size() );
|
|
|
|
|
blocks.push_back( block );
|
|
|
|
|
}
|
|
|
|
|
void EScriptProgram::leaveblock()
|
|
|
|
|
{
|
|
|
|
|
passert( curblock );
|
|
|
|
|
bool remove = blocks[curblock].localvarnames.empty() && curblock == blocks.size() - 1;
|
|
|
|
|
curblock = blocks[curblock].parentblockidx;
|
|
|
|
|
if ( remove )
|
|
|
|
|
{
|
|
|
|
|
blocks.pop_back();
|
|
|
|
|
for ( auto& elem : dbg_ins_blocks )
|
2016-02-11 22:54:43 +01:00
|
|
|
{
|
2016-02-19 19:26:35 +01:00
|
|
|
if ( elem >= blocks.size() )
|
|
|
|
|
elem = curblock;
|
2016-02-11 22:54:43 +01:00
|
|
|
}
|
|
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
void EScriptProgram::addlocalvar( const std::string& localvarname )
|
|
|
|
|
{
|
|
|
|
|
blocks[curblock].localvarnames.push_back( localvarname );
|
|
|
|
|
}
|
|
|
|
|
void EScriptProgram::addfunction( std::string funcname, unsigned firstPC, unsigned lastPC )
|
|
|
|
|
{
|
|
|
|
|
EPDbgFunction func;
|
|
|
|
|
func.name = funcname;
|
|
|
|
|
func.firstPC = firstPC;
|
|
|
|
|
func.lastPC = lastPC;
|
|
|
|
|
dbg_functions.push_back( func );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t EScriptProgram::sizeEstimate() const
|
|
|
|
|
{
|
|
|
|
|
size_t size = sizeof( EScriptProgram ) + program_decl.capacity();
|
|
|
|
|
size += 3 * sizeof( std::string* ) + sourcelines.capacity() * sizeof( std::string );
|
|
|
|
|
for ( const auto& l : sourcelines )
|
|
|
|
|
size += l.capacity();
|
|
|
|
|
size += 3 * sizeof( std::string* ) + fileline.capacity() * sizeof( std::string );
|
|
|
|
|
for ( const auto& l : fileline )
|
|
|
|
|
size += l.capacity();
|
|
|
|
|
size += 3 * sizeof( std::string* ) + function_decls.capacity() * sizeof( std::string );
|
|
|
|
|
for ( const auto& l : function_decls )
|
|
|
|
|
size += l.capacity();
|
|
|
|
|
size += 3 * sizeof( std::string* ) + globalvarnames.capacity() * sizeof( std::string );
|
|
|
|
|
for ( const auto& l : globalvarnames )
|
|
|
|
|
size += l.capacity();
|
|
|
|
|
size += 3 * sizeof( std::string* ) + dbg_filenames.capacity() * sizeof( std::string );
|
|
|
|
|
for ( const auto& l : dbg_filenames )
|
|
|
|
|
size += l.capacity();
|
|
|
|
|
size += 3 * sizeof( unsigned* ) + dbg_filenum.capacity() * sizeof( unsigned );
|
|
|
|
|
size += 3 * sizeof( unsigned* ) + dbg_linenum.capacity() * sizeof( unsigned );
|
|
|
|
|
size += 3 * sizeof( unsigned* ) + dbg_ins_blocks.capacity() * sizeof( unsigned );
|
|
|
|
|
size += 3 * sizeof( bool* ) + dbg_ins_statementbegin.capacity() * sizeof( bool );
|
|
|
|
|
|
|
|
|
|
size += 3 * sizeof( FunctionalityModule** ) + modules.capacity() * sizeof( FunctionalityModule* );
|
|
|
|
|
size += 3 * sizeof( EPExportedFunction* ) +
|
|
|
|
|
exported_functions.capacity() * sizeof( EPExportedFunction );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
size += 3 * sizeof( Instruction* ) + instr.capacity() * sizeof( Instruction );
|
|
|
|
|
|
|
|
|
|
size += 3 * sizeof( EPDbgBlock* ) + blocks.capacity() * sizeof( EPDbgBlock );
|
|
|
|
|
size += 3 * sizeof( EPDbgFunction* ) + dbg_functions.capacity() * sizeof( EPDbgFunction );
|
|
|
|
|
|
|
|
|
|
return size;
|
|
|
|
|
}
|
2019-08-25 09:05:15 +02:00
|
|
|
} // namespace Bscript
|
|
|
|
|
} // namespace Pol
|