2000-09-18 15:18:56 +00:00
|
|
|
|
/*************************************************************************
|
|
|
|
|
*
|
2008-04-11 10:44:31 +00:00
|
|
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
2005-09-29 11:39:01 +00:00
|
|
|
|
*
|
2010-02-12 15:01:35 +01:00
|
|
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
2005-09-29 11:39:01 +00:00
|
|
|
|
*
|
2008-04-11 10:44:31 +00:00
|
|
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
2000-09-18 15:18:56 +00:00
|
|
|
|
*
|
2008-04-11 10:44:31 +00:00
|
|
|
|
* This file is part of OpenOffice.org.
|
2000-09-18 15:18:56 +00:00
|
|
|
|
*
|
2008-04-11 10:44:31 +00:00
|
|
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
|
|
|
* only, as published by the Free Software Foundation.
|
2000-09-18 15:18:56 +00:00
|
|
|
|
*
|
2008-04-11 10:44:31 +00:00
|
|
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU Lesser General Public License version 3 for more details
|
|
|
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
2000-09-18 15:18:56 +00:00
|
|
|
|
*
|
2008-04-11 10:44:31 +00:00
|
|
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
|
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
|
|
|
* <http://www.openoffice.org/license.html>
|
|
|
|
|
* for a copy of the LGPLv3 License.
|
2000-09-18 15:18:56 +00:00
|
|
|
|
*
|
|
|
|
|
************************************************************************/
|
|
|
|
|
|
2006-09-17 08:59:37 +00:00
|
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
|
|
|
#include "precompiled_basic.hxx"
|
|
|
|
|
|
2000-09-18 15:18:56 +00:00
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <tools/stream.hxx>
|
2007-06-27 13:18:06 +00:00
|
|
|
|
#include <basic/sbx.hxx>
|
2000-09-18 15:18:56 +00:00
|
|
|
|
#include "sb.hxx"
|
|
|
|
|
#include "iosys.hxx"
|
|
|
|
|
#include "disas.hxx"
|
2010-07-26 14:20:03 +02:00
|
|
|
|
#include "sbtrace.hxx"
|
2000-09-18 15:18:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const char* pOp1[] = {
|
|
|
|
|
"NOP",
|
|
|
|
|
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// Operators
|
|
|
|
|
// the following operators have the same order as in
|
|
|
|
|
// enum SbxVarOp
|
2000-09-18 15:18:56 +00:00
|
|
|
|
"EXP", "MUL", "DIV", "MOD", "PLUS", "MINUS", "NEG",
|
|
|
|
|
"EQ", "NE", "LT", "GT", "LE", "GE",
|
|
|
|
|
"IDIV", "AND", "OR", "XOR", "EQV", "IMP", "NOT",
|
|
|
|
|
"CAT",
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// End enum SbxVarOp
|
2000-09-18 15:18:56 +00:00
|
|
|
|
"LIKE", "IS",
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// Load/Store
|
|
|
|
|
"ARGC", // Create new Argv
|
|
|
|
|
"ARGV", // TOS ==> current Argv
|
2000-09-18 15:18:56 +00:00
|
|
|
|
"INPUT", // Input ==> TOS
|
|
|
|
|
"LINPUT", // Line Input ==> TOS
|
2009-04-25 00:18:20 +00:00
|
|
|
|
"GET", // get TOS
|
|
|
|
|
"SET", // Save Object TOS ==> TOS-1
|
2000-09-18 15:18:56 +00:00
|
|
|
|
"PUT", // TOS ==> TOS-1
|
2009-04-25 00:18:20 +00:00
|
|
|
|
"CONST", // TOS ==> TOS-1, then ReadOnly
|
2000-09-18 15:18:56 +00:00
|
|
|
|
"DIM", // DIM
|
|
|
|
|
"REDIM", // REDIM
|
|
|
|
|
"REDIMP", // REDIM PRESERVE
|
2009-04-25 00:18:20 +00:00
|
|
|
|
"ERASE", // delete TOS
|
|
|
|
|
// Branch
|
|
|
|
|
"STOP", // End of program
|
|
|
|
|
"INITFOR", // FOR-Variable init
|
|
|
|
|
"NEXT", // FOR-Variable increment
|
|
|
|
|
"CASE", // Begin CASE
|
|
|
|
|
"ENDCASE", // End CASE
|
|
|
|
|
"STDERR", // Default error handling
|
|
|
|
|
"NOERROR", // No error handling
|
|
|
|
|
"LEAVE", // leave UP
|
|
|
|
|
// I/O
|
|
|
|
|
"CHANNEL", // TOS = Channelnumber
|
2000-09-18 15:18:56 +00:00
|
|
|
|
"PRINT", // print TOS
|
|
|
|
|
"PRINTF", // print TOS in field
|
|
|
|
|
"WRITE", // write TOS
|
|
|
|
|
"RENAME", // Rename Tos+1 to Tos
|
|
|
|
|
"PROMPT", // TOS = Prompt for Input
|
2009-04-25 00:18:20 +00:00
|
|
|
|
"RESTART", // Define restart point
|
|
|
|
|
"STDIO", // Switch to I/O channel 0
|
|
|
|
|
// Misc
|
|
|
|
|
"EMPTY", // Empty statement to stack
|
|
|
|
|
"ERROR", // TOS = error code
|
|
|
|
|
"LSET", // Save object TOS ==> TOS-1
|
|
|
|
|
"RSET", // Save object TOS ==> TOS-1 (TODO: Same as above?)
|
2005-01-28 15:05:09 +00:00
|
|
|
|
"REDIMP_ERASE",
|
2007-08-03 08:54:50 +00:00
|
|
|
|
"INITFOREACH",
|
2008-06-24 15:01:06 +00:00
|
|
|
|
"VBASET",
|
|
|
|
|
"ERASE_CLEAR",
|
2010-06-15 20:02:53 +02:00
|
|
|
|
"ARRAYACCESS",
|
|
|
|
|
"BYVAL"
|
2000-09-18 15:18:56 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const char* pOp2[] = {
|
2009-04-25 00:18:20 +00:00
|
|
|
|
"NUMBER", // Load a numeric constant (+ID)
|
|
|
|
|
"STRING", // Load a string constant (+ID)
|
|
|
|
|
"CONSTANT", // Immediate Load (+value)
|
|
|
|
|
"ARGN", // Save named args in argv (+StringID)
|
|
|
|
|
"PAD", // Pad String to defined length (+length)
|
|
|
|
|
// Branches
|
|
|
|
|
"JUMP", // Jump to target (+Target)
|
|
|
|
|
"JUMP.T", // evaluate TOS, conditional jump (+Target)
|
|
|
|
|
"JUMP.F", // evaluate TOS, conditional jump (+Target)
|
|
|
|
|
"ONJUMP", // evaluate TOS, jump into JUMP-table (+MaxVal)
|
|
|
|
|
"GOSUB", // UP-Call (+Target)
|
|
|
|
|
"RETURN", // UP-Return (+0 or Target)
|
|
|
|
|
"TESTFOR", // Test FOR-Variable, increment (+Endlabel)
|
|
|
|
|
"CASETO", // Tos+1 <= Case <= Tos, 2xremove (+Target)
|
|
|
|
|
"ERRHDL", // Error-Handler (+Offset)
|
|
|
|
|
"RESUME", // Resume after errors (+0 or 1 or Label)
|
|
|
|
|
// I/O
|
|
|
|
|
"CLOSE", // (+channel/0)
|
|
|
|
|
"PRCHAR", // (+char)
|
|
|
|
|
// Objects
|
|
|
|
|
"SETCLASS", // Test Set + Classname (+StringId)
|
|
|
|
|
"TESTCLASS", // Check TOS class (+StringId)
|
|
|
|
|
"LIB", // Set Libname for Declare-Procs (+StringId)
|
|
|
|
|
// New since Beta 3 (TODO: Which Beta3?)
|
|
|
|
|
"BASED", // TOS is incremted about BASE, push BASE before
|
|
|
|
|
"ARGTYP", // Convert last parameter in argv (+Type)
|
2008-06-24 15:01:06 +00:00
|
|
|
|
"VBASETCLASS",
|
2000-09-18 15:18:56 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const char* pOp3[] = {
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// All opcodes with two operands
|
|
|
|
|
"RTL", // Load from RTL (+StringID+Typ)
|
|
|
|
|
"FIND", // Load (+StringID+Typ)
|
|
|
|
|
"ELEM", // Load element (+StringID+Typ)
|
2000-09-18 15:18:56 +00:00
|
|
|
|
"PARAM", // Parameter (+Offset+Typ)
|
2009-04-25 00:18:20 +00:00
|
|
|
|
|
|
|
|
|
// Branching
|
|
|
|
|
"CALL", // Call DECLARE method (+StringID+Typ)
|
|
|
|
|
"CALL.C", // Call Cdecl-DECLARE method (+StringID+Typ)
|
2000-09-18 15:18:56 +00:00
|
|
|
|
"CASEIS", // Case-Test (+Test-Opcode+False-Target)
|
2009-04-25 00:18:20 +00:00
|
|
|
|
"STMNT", // Start of a statement (+Line+Col)
|
|
|
|
|
|
|
|
|
|
// I/O
|
2000-09-18 15:18:56 +00:00
|
|
|
|
"OPEN", // (+SvStreamFlags+Flags)
|
2009-04-25 00:18:20 +00:00
|
|
|
|
|
|
|
|
|
// Objects and variables
|
|
|
|
|
"LOCAL", // Local variables (+StringID+Typ)
|
|
|
|
|
"PUBLIC", // Modul global var (+StringID+Typ)
|
|
|
|
|
"GLOBAL", // Global var (+StringID+Typ)
|
|
|
|
|
"CREATE", // Create object (+StringId+StringId)
|
|
|
|
|
"STATIC", // Create static object (+StringId+StringId)
|
|
|
|
|
"TCREATE", // Create User defined Object (+StringId+StringId)
|
|
|
|
|
"DCREATE", // Create User defined Object-Array kreieren (+StringId+StringId)
|
|
|
|
|
"GLOBAL_P", // Define persistent global var (existing after basic restart)
|
|
|
|
|
// P=PERSIST (+StringID+Typ)
|
|
|
|
|
"FIND_G", // Searches for global var with special handling due to _GLOBAL_P
|
|
|
|
|
"DCREATE_REDIMP", // Change dimensions of a user defined Object-Array (+StringId+StringId)
|
2004-11-02 10:49:05 +00:00
|
|
|
|
"FIND_CM", // Search inside a class module (CM) to enable global search in time
|
2008-06-24 15:01:06 +00:00
|
|
|
|
"PUBLIC_P", // Module global Variable (persisted between calls)(+StringID+Typ)
|
2010-07-07 14:58:53 +02:00
|
|
|
|
"FIND_STATIC", // local static var lookup (+StringID+Typ)
|
2000-09-18 15:18:56 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const char** pOps[3] = { pOp1, pOp2, pOp3 };
|
|
|
|
|
|
2009-04-25 00:18:20 +00:00
|
|
|
|
typedef void( SbiDisas::*Func )( String& ); // Processing routines
|
2000-09-18 15:18:56 +00:00
|
|
|
|
|
|
|
|
|
static const Func pOperand2[] = {
|
2009-04-25 00:18:20 +00:00
|
|
|
|
&SbiDisas::StrOp, // Load a numeric constant (+ID)
|
|
|
|
|
&SbiDisas::StrOp, // Load a string constant (+ID)
|
2006-10-12 13:24:40 +00:00
|
|
|
|
&SbiDisas::ImmOp, // Immediate Load (+Wert)
|
2009-04-25 00:18:20 +00:00
|
|
|
|
&SbiDisas::StrOp, // Save a named argument (+ID)
|
|
|
|
|
&SbiDisas::ImmOp, // Strip String to fixed size (+length)
|
|
|
|
|
|
|
|
|
|
// Branches
|
|
|
|
|
&SbiDisas::LblOp, // Jump (+Target)
|
|
|
|
|
&SbiDisas::LblOp, // eval TOS, conditional jump (+Target)
|
|
|
|
|
&SbiDisas::LblOp, // eval TOS, conditional jump (+Target)
|
|
|
|
|
&SbiDisas::OnOp, // eval TOS, jump in JUMP table (+MaxVal)
|
|
|
|
|
&SbiDisas::LblOp, // UP call (+Target)
|
|
|
|
|
&SbiDisas::ReturnOp, // UP Return (+0 or Target)
|
|
|
|
|
&SbiDisas::LblOp, // test FOR-Variable, increment (+Endlabel)
|
2006-10-12 13:24:40 +00:00
|
|
|
|
&SbiDisas::LblOp, // Tos+1 <= Case <= Tos), 2xremove (+Target)
|
2009-04-25 00:18:20 +00:00
|
|
|
|
&SbiDisas::LblOp, // Error handler (+Offset)
|
|
|
|
|
&SbiDisas::ResumeOp, // Resume after errors (+0 or 1 or Label)
|
|
|
|
|
|
|
|
|
|
// I/O
|
|
|
|
|
&SbiDisas::CloseOp, // (+channel/0)
|
2006-10-12 13:24:40 +00:00
|
|
|
|
&SbiDisas::CharOp, // (+char)
|
2009-04-25 00:18:20 +00:00
|
|
|
|
|
|
|
|
|
// Objects
|
|
|
|
|
&SbiDisas::StrOp, // Test classname (+StringId)
|
2006-10-12 13:24:40 +00:00
|
|
|
|
&SbiDisas::StrOp, // TESTCLASS, Check TOS class (+StringId)
|
2009-04-25 00:18:20 +00:00
|
|
|
|
&SbiDisas::StrOp, // Set libname for declare procs (+StringId)
|
|
|
|
|
&SbiDisas::ImmOp, // TOS is incremented about BASE erhoeht, BASE pushed before
|
|
|
|
|
&SbiDisas::TypeOp, // Convert last parameter to/in(?) argv (+Typ)
|
2008-06-24 15:01:06 +00:00
|
|
|
|
&SbiDisas::StrOp, // VBASETCLASS (+StringId)
|
2000-09-18 15:18:56 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const Func pOperand3[] = {
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// All opcodes with two operands
|
|
|
|
|
&SbiDisas::VarOp, // Load from RTL (+StringID+Typ)
|
|
|
|
|
&SbiDisas::VarOp, // Load (+StringID+Typ)
|
|
|
|
|
&SbiDisas::VarOp, // Load Element (+StringID+Typ)
|
2006-10-12 13:24:40 +00:00
|
|
|
|
&SbiDisas::OffOp, // Parameter (+Offset+Typ)
|
2009-04-25 00:18:20 +00:00
|
|
|
|
|
|
|
|
|
// Branch
|
|
|
|
|
&SbiDisas::VarOp, // Call DECLARE-Method (+StringID+Typ)
|
|
|
|
|
&SbiDisas::VarOp, // Call CDecl-DECLARE-Methode (+StringID+Typ)
|
2006-10-12 13:24:40 +00:00
|
|
|
|
&SbiDisas::CaseOp, // Case-Test (+Test-Opcode+False-Target)
|
2009-04-25 00:18:20 +00:00
|
|
|
|
&SbiDisas::StmntOp, // Statement (+Row+Column)
|
|
|
|
|
|
|
|
|
|
// I/O
|
2006-10-12 13:24:40 +00:00
|
|
|
|
&SbiDisas::StrmOp, // (+SvStreamFlags+Flags)
|
2009-04-25 00:18:20 +00:00
|
|
|
|
|
|
|
|
|
// Objects
|
|
|
|
|
&SbiDisas::VarDefOp, // Define local var (+StringID+Typ)
|
|
|
|
|
&SbiDisas::VarDefOp, // Define Module global var (+StringID+Typ)
|
|
|
|
|
&SbiDisas::VarDefOp, // Define global var (+StringID+Typ)
|
|
|
|
|
&SbiDisas::Str2Op, // Create object (+StringId+StringId)
|
|
|
|
|
&SbiDisas::VarDefOp, // Define static object (+StringID+Typ)
|
|
|
|
|
&SbiDisas::Str2Op, // Create User defined Object (+StringId+StringId)
|
|
|
|
|
&SbiDisas::Str2Op, // Create User defined Object-Array (+StringId+StringId)
|
|
|
|
|
&SbiDisas::VarDefOp, // Define persistent global var P=PERSIST (+StringID+Typ)
|
|
|
|
|
&SbiDisas::VarOp, // Searches for global var with special handling due to _GLOBAL_P
|
|
|
|
|
&SbiDisas::Str2Op, // Redimensionate User defined Object-Array (+StringId+StringId)
|
2008-06-24 15:01:06 +00:00
|
|
|
|
&SbiDisas::VarOp, // FIND_CM
|
|
|
|
|
&SbiDisas::VarDefOp, // PUBLIC_P
|
2010-07-07 14:58:53 +02:00
|
|
|
|
&SbiDisas::VarOp, // FIND_STATIC
|
2000-09-18 15:18:56 +00:00
|
|
|
|
};
|
|
|
|
|
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// TODO: Why as method? Isn't a simple define sufficient?
|
2000-09-18 15:18:56 +00:00
|
|
|
|
static const char* _crlf()
|
|
|
|
|
{
|
2006-06-19 16:38:48 +00:00
|
|
|
|
#if defined (UNX) || defined( PM2 )
|
2000-09-18 15:18:56 +00:00
|
|
|
|
return "\n";
|
|
|
|
|
#else
|
|
|
|
|
return "\r\n";
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// This method exists because we want to load the file as own segment
|
2000-09-18 15:18:56 +00:00
|
|
|
|
BOOL SbModule::Disassemble( String& rText )
|
|
|
|
|
{
|
|
|
|
|
rText.Erase();
|
|
|
|
|
if( pImage )
|
|
|
|
|
{
|
|
|
|
|
SbiDisas aDisas( this, pImage );
|
|
|
|
|
aDisas.Disas( rText );
|
|
|
|
|
}
|
|
|
|
|
return BOOL( rText.Len() != 0 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SbiDisas::SbiDisas( SbModule* p, const SbiImage* q ) : rImg( *q ), pMod( p )
|
|
|
|
|
{
|
|
|
|
|
memset( cLabels, 0, 8192 );
|
2006-11-03 06:19:02 +00:00
|
|
|
|
nLine = 0;
|
|
|
|
|
nOff = 0;
|
|
|
|
|
nPC = 0;
|
2008-06-24 15:01:06 +00:00
|
|
|
|
nOp1 = nOp2 = nParts = 0;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
eOp = _NOP;
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// Set Label-Bits
|
2000-09-18 15:18:56 +00:00
|
|
|
|
nOff = 0;
|
|
|
|
|
while( Fetch() )
|
|
|
|
|
{
|
|
|
|
|
switch( eOp )
|
|
|
|
|
{
|
|
|
|
|
case _RESUME: if( nOp1 <= 1 ) break;
|
|
|
|
|
case _RETURN: if( !nOp1 ) break;
|
|
|
|
|
case _JUMP:
|
|
|
|
|
case _JUMPT:
|
|
|
|
|
case _JUMPF:
|
|
|
|
|
case _GOSUB:
|
|
|
|
|
case _TESTFOR:
|
|
|
|
|
case _CASEIS:
|
|
|
|
|
case _CASETO:
|
2006-10-12 13:24:40 +00:00
|
|
|
|
case _ERRHDL:
|
2008-06-24 15:01:06 +00:00
|
|
|
|
cLabels[ (nOp1 & 0xffff) >> 3 ] |= ( 1 << ( nOp1 & 7 ) );
|
2006-10-12 13:24:40 +00:00
|
|
|
|
break;
|
2006-06-19 16:38:48 +00:00
|
|
|
|
default: break;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
nOff = 0;
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// Add the publics
|
2000-09-18 15:18:56 +00:00
|
|
|
|
for( USHORT i = 0; i < pMod->GetMethods()->Count(); i++ )
|
|
|
|
|
{
|
|
|
|
|
SbMethod* pMeth = PTR_CAST(SbMethod,pMod->GetMethods()->Get( i ));
|
|
|
|
|
if( pMeth )
|
|
|
|
|
{
|
2006-11-03 06:19:02 +00:00
|
|
|
|
USHORT nPos = (USHORT) (pMeth->GetId());
|
2000-09-18 15:18:56 +00:00
|
|
|
|
cLabels[ nPos >> 3 ] |= ( 1 << ( nPos & 7 ) );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// Read current opcode
|
2000-09-18 15:18:56 +00:00
|
|
|
|
BOOL SbiDisas::Fetch()
|
|
|
|
|
{
|
|
|
|
|
nPC = nOff;
|
|
|
|
|
if( nOff >= rImg.GetCodeSize() )
|
|
|
|
|
return FALSE;
|
2008-06-24 15:01:06 +00:00
|
|
|
|
const unsigned char* p = (const unsigned char*)( rImg.GetCode() + nOff );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
eOp = (SbiOpcode) ( *p++ & 0xFF );
|
|
|
|
|
if( eOp <= SbOP0_END )
|
|
|
|
|
{
|
|
|
|
|
nOp1 = nOp2 = 0;
|
|
|
|
|
nParts = 1;
|
|
|
|
|
nOff++;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
else if( eOp <= SbOP1_END )
|
|
|
|
|
{
|
2008-06-24 15:01:06 +00:00
|
|
|
|
nOff += 5;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
if( nOff > rImg.GetCodeSize() )
|
|
|
|
|
return FALSE;
|
2008-06-24 15:01:06 +00:00
|
|
|
|
nOp1 = *p++; nOp1 |= *p++ << 8; nOp1 |= *p++ << 16; nOp1 |= *p++ << 24;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
nParts = 2;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
else if( eOp <= SbOP2_END )
|
|
|
|
|
{
|
2008-06-24 15:01:06 +00:00
|
|
|
|
nOff += 9;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
if( nOff > rImg.GetCodeSize() )
|
|
|
|
|
return FALSE;
|
2008-06-24 15:01:06 +00:00
|
|
|
|
nOp1 = *p++; nOp1 |= *p++ << 8; nOp1 |= *p++ << 16; nOp1 |= *p++ << 24;
|
|
|
|
|
nOp2 = *p++; nOp2 |= *p++ << 8; nOp2 |= *p++ << 16; nOp2 |= *p++ << 24;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
nParts = 3;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SbiDisas::Disas( SvStream& r )
|
|
|
|
|
{
|
|
|
|
|
String aText;
|
|
|
|
|
nOff = 0;
|
|
|
|
|
while( DisasLine( aText ) )
|
|
|
|
|
{
|
|
|
|
|
ByteString aByteText( aText, gsl_getSystemTextEncoding() );
|
|
|
|
|
r.WriteLine( aByteText );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SbiDisas::Disas( String& r )
|
|
|
|
|
{
|
|
|
|
|
r.Erase();
|
|
|
|
|
String aText;
|
|
|
|
|
nOff = 0;
|
|
|
|
|
while( DisasLine( aText ) )
|
|
|
|
|
{
|
|
|
|
|
r += aText;
|
|
|
|
|
r.AppendAscii( _crlf() );
|
|
|
|
|
}
|
|
|
|
|
aText.ConvertLineEnd();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL SbiDisas::DisasLine( String& rText )
|
|
|
|
|
{
|
2008-06-24 15:01:06 +00:00
|
|
|
|
char cBuf[ 100 ];
|
2000-09-18 15:18:56 +00:00
|
|
|
|
const char* pMask[] = {
|
2008-06-24 15:01:06 +00:00
|
|
|
|
"%08" SAL_PRIXUINT32 " ",
|
|
|
|
|
"%08" SAL_PRIXUINT32 " %02X ",
|
|
|
|
|
"%08" SAL_PRIXUINT32 " %02X %08X ",
|
|
|
|
|
"%08" SAL_PRIXUINT32 " %02X %08X %08X " };
|
2000-09-18 15:18:56 +00:00
|
|
|
|
rText.Erase();
|
|
|
|
|
if( !Fetch() )
|
|
|
|
|
return FALSE;
|
2010-07-26 14:20:03 +02:00
|
|
|
|
|
|
|
|
|
#ifdef DBG_TRACE_BASIC
|
|
|
|
|
String aTraceStr_STMNT;
|
|
|
|
|
#endif
|
|
|
|
|
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// New line?
|
2008-06-24 15:01:06 +00:00
|
|
|
|
if( eOp == _STMNT && nOp1 != nLine )
|
2000-09-18 15:18:56 +00:00
|
|
|
|
{
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// Find line
|
2003-04-23 15:55:41 +00:00
|
|
|
|
String aSource = rImg.aOUSource;
|
2008-06-24 15:01:06 +00:00
|
|
|
|
nLine = nOp1;
|
|
|
|
|
USHORT n = 0;
|
|
|
|
|
USHORT l = (USHORT)nLine;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
while( --l ) {
|
2003-04-23 15:55:41 +00:00
|
|
|
|
n = aSource.SearchAscii( "\n", n );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
if( n == STRING_NOTFOUND ) break;
|
|
|
|
|
else n++;
|
|
|
|
|
}
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// Show position
|
2000-09-18 15:18:56 +00:00
|
|
|
|
if( n != STRING_NOTFOUND )
|
|
|
|
|
{
|
2003-04-23 15:55:41 +00:00
|
|
|
|
USHORT n2 = aSource.SearchAscii( "\n", n );
|
|
|
|
|
if( n2 == STRING_NOTFOUND ) n2 = aSource.Len() - n;
|
|
|
|
|
String s( aSource.Copy( n, n2 - n + 1 ) );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
BOOL bDone;
|
|
|
|
|
do {
|
|
|
|
|
bDone = TRUE;
|
|
|
|
|
n = s.Search( '\r' );
|
|
|
|
|
if( n != STRING_NOTFOUND ) bDone = FALSE, s.Erase( n, 1 );
|
|
|
|
|
n = s.Search( '\n' );
|
|
|
|
|
if( n != STRING_NOTFOUND ) bDone = FALSE, s.Erase( n, 1 );
|
|
|
|
|
} while( !bDone );
|
2003-03-18 15:28:40 +00:00
|
|
|
|
// snprintf( cBuf, sizeof(cBuf), pMask[ 0 ], nPC );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
// rText += cBuf;
|
|
|
|
|
rText.AppendAscii( "; " );
|
|
|
|
|
rText += s;
|
|
|
|
|
rText.AppendAscii( _crlf() );
|
2010-07-26 14:20:03 +02:00
|
|
|
|
|
|
|
|
|
#ifdef DBG_TRACE_BASIC
|
|
|
|
|
aTraceStr_STMNT = s;
|
|
|
|
|
#endif
|
2000-09-18 15:18:56 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2010-07-26 14:20:03 +02:00
|
|
|
|
|
2000-09-18 15:18:56 +00:00
|
|
|
|
// Label?
|
|
|
|
|
const char* p = "";
|
|
|
|
|
if( cLabels[ nPC >> 3 ] & ( 1 << ( nPC & 7 ) ) )
|
|
|
|
|
{
|
|
|
|
|
// Public?
|
|
|
|
|
ByteString aByteMethName;
|
|
|
|
|
for( USHORT i = 0; i < pMod->GetMethods()->Count(); i++ )
|
|
|
|
|
{
|
|
|
|
|
SbMethod* pMeth = PTR_CAST(SbMethod,pMod->GetMethods()->Get( i ));
|
|
|
|
|
if( pMeth )
|
|
|
|
|
{
|
|
|
|
|
aByteMethName = ByteString( pMeth->GetName(), gsl_getSystemTextEncoding() );
|
|
|
|
|
if( pMeth->GetId() == nPC )
|
|
|
|
|
{
|
|
|
|
|
p = aByteMethName.GetBuffer();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if( pMeth->GetId() >= nPC )
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-03-18 15:28:40 +00:00
|
|
|
|
snprintf( cBuf, sizeof(cBuf), pMask[ 0 ], nPC );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
rText.AppendAscii( cBuf );
|
|
|
|
|
if( p && *p )
|
|
|
|
|
{
|
|
|
|
|
rText.AppendAscii( p );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2006-11-01 15:12:48 +00:00
|
|
|
|
// fix warning (now error) for "Lbl%04lX" format
|
2008-01-28 12:59:35 +00:00
|
|
|
|
snprintf( cBuf, sizeof(cBuf), "Lbl%08" SAL_PRIXUINT32, nPC );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
rText.AppendAscii( cBuf );
|
|
|
|
|
}
|
|
|
|
|
rText += ':';
|
|
|
|
|
rText.AppendAscii( _crlf() );
|
|
|
|
|
}
|
2003-03-18 15:28:40 +00:00
|
|
|
|
snprintf( cBuf, sizeof(cBuf), pMask[ nParts ], nPC, (USHORT) eOp, nOp1, nOp2 );
|
2010-07-26 14:20:03 +02:00
|
|
|
|
|
|
|
|
|
String aPCodeStr;
|
|
|
|
|
aPCodeStr.AppendAscii( cBuf );
|
2006-10-12 13:24:40 +00:00
|
|
|
|
int n = eOp;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
if( eOp >= SbOP2_START )
|
|
|
|
|
n -= SbOP2_START;
|
|
|
|
|
else if( eOp >= SbOP1_START )
|
|
|
|
|
n -= SbOP1_START;
|
2010-07-26 14:20:03 +02:00
|
|
|
|
aPCodeStr += '\t';
|
|
|
|
|
aPCodeStr.AppendAscii( pOps[ nParts-1 ][ n ] );
|
|
|
|
|
aPCodeStr += '\t';
|
2000-09-18 15:18:56 +00:00
|
|
|
|
switch( nParts )
|
|
|
|
|
{
|
2010-07-26 14:20:03 +02:00
|
|
|
|
case 2: (this->*( pOperand2[ n ] ) )( aPCodeStr ); break;
|
|
|
|
|
case 3: (this->*( pOperand3[ n ] ) )( aPCodeStr ); break;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
}
|
2010-07-26 14:20:03 +02:00
|
|
|
|
|
|
|
|
|
rText += aPCodeStr;
|
|
|
|
|
|
|
|
|
|
#ifdef DBG_TRACE_BASIC
|
|
|
|
|
dbg_RegisterTraceTextForPC( pMod, nPC, aTraceStr_STMNT, aPCodeStr );
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-09-18 15:18:56 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// Read from StringPool
|
2000-09-18 15:18:56 +00:00
|
|
|
|
void SbiDisas::StrOp( String& rText )
|
|
|
|
|
{
|
2008-06-24 15:01:06 +00:00
|
|
|
|
String aStr = rImg.GetString( (USHORT)nOp1 );
|
2003-03-18 15:28:40 +00:00
|
|
|
|
ByteString aByteString( aStr, RTL_TEXTENCODING_ASCII_US );
|
|
|
|
|
const char* p = aByteString.GetBuffer();
|
2000-09-18 15:18:56 +00:00
|
|
|
|
if( p )
|
|
|
|
|
{
|
|
|
|
|
rText += '"';
|
|
|
|
|
rText.AppendAscii( p );
|
|
|
|
|
rText += '"';
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rText.AppendAscii( "?String? " );
|
2008-06-24 15:01:06 +00:00
|
|
|
|
rText += (USHORT)nOp1;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SbiDisas::Str2Op( String& rText )
|
|
|
|
|
{
|
|
|
|
|
StrOp( rText );
|
|
|
|
|
rText += ',';
|
|
|
|
|
String s;
|
|
|
|
|
nOp1 = nOp2;
|
|
|
|
|
StrOp( s );
|
|
|
|
|
rText += s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Immediate Operand
|
|
|
|
|
void SbiDisas::ImmOp( String& rText )
|
|
|
|
|
{
|
2004-11-15 15:33:47 +00:00
|
|
|
|
rText += String::CreateFromInt32(nOp1);
|
2000-09-18 15:18:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// OnGoto Operand
|
|
|
|
|
void SbiDisas::OnOp( String& rText )
|
|
|
|
|
{
|
2004-02-26 11:59:43 +00:00
|
|
|
|
rText += String::CreateFromInt32(nOp1 & 0x7FFF);
|
2000-09-18 15:18:56 +00:00
|
|
|
|
if( nOp1 & 0x800 )
|
|
|
|
|
rText.AppendAscii( "\t; Gosub" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Label
|
|
|
|
|
void SbiDisas::LblOp( String& rText )
|
|
|
|
|
{
|
|
|
|
|
char cBuf[ 10 ];
|
2008-06-24 15:01:06 +00:00
|
|
|
|
snprintf( cBuf, sizeof(cBuf), "Lbl%04" SAL_PRIXUINT32, nOp1 );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
rText.AppendAscii( cBuf );
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// 0 or Label
|
2000-09-18 15:18:56 +00:00
|
|
|
|
void SbiDisas::ReturnOp( String& rText )
|
|
|
|
|
{
|
|
|
|
|
if( nOp1 )
|
|
|
|
|
LblOp( rText );
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// 0, 1 or Label
|
2000-09-18 15:18:56 +00:00
|
|
|
|
void SbiDisas::ResumeOp( String& rText )
|
|
|
|
|
{
|
|
|
|
|
switch( nOp1 )
|
|
|
|
|
{
|
|
|
|
|
case 1: rText.AppendAscii( "NEXT" ); break;
|
|
|
|
|
case 2: LblOp( rText );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// print Prompt
|
2000-09-18 15:18:56 +00:00
|
|
|
|
// FALSE/TRUE
|
|
|
|
|
void SbiDisas::PromptOp( String& rText )
|
|
|
|
|
{
|
|
|
|
|
if( nOp1 )
|
|
|
|
|
rText.AppendAscii( "\"? \"" );
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// 0 or 1
|
2000-09-18 15:18:56 +00:00
|
|
|
|
void SbiDisas::CloseOp( String& rText )
|
|
|
|
|
{
|
|
|
|
|
rText.AppendAscii( nOp1 ? "Channel" : "All" );
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// Print character
|
2000-09-18 15:18:56 +00:00
|
|
|
|
void SbiDisas::CharOp( String& rText )
|
|
|
|
|
{
|
|
|
|
|
const char* p = NULL;
|
|
|
|
|
switch( nOp1 )
|
|
|
|
|
{
|
|
|
|
|
case 7: p = "'\\a'"; break;
|
|
|
|
|
case 9: p = "'\\t'"; break;
|
|
|
|
|
case 10: p = "'\\n'"; break;
|
|
|
|
|
case 12: p = "'\\f'"; break;
|
|
|
|
|
case 13: p = "'\\r'"; break;
|
|
|
|
|
}
|
|
|
|
|
if( p ) rText.AppendAscii( p );
|
|
|
|
|
else if( nOp1 >= ' ' )
|
|
|
|
|
rText += '\'',
|
|
|
|
|
rText += (char) nOp1,
|
|
|
|
|
rText += '\'';
|
|
|
|
|
else
|
|
|
|
|
rText.AppendAscii( "char " ),
|
2008-06-24 15:01:06 +00:00
|
|
|
|
rText += (USHORT)nOp1;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// Print var: String-ID and type
|
2000-09-18 15:18:56 +00:00
|
|
|
|
void SbiDisas::VarOp( String& rText )
|
|
|
|
|
{
|
2008-06-24 15:01:06 +00:00
|
|
|
|
rText += rImg.GetString( (USHORT)(nOp1 & 0x7FFF) );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
rText.AppendAscii( "\t; " );
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// The type
|
2008-06-24 15:01:06 +00:00
|
|
|
|
UINT32 n = nOp1;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
nOp1 = nOp2;
|
|
|
|
|
TypeOp( rText );
|
|
|
|
|
if( n & 0x8000 )
|
|
|
|
|
rText.AppendAscii( ", Args" );
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// Define variable: String-ID and type
|
2000-09-18 15:18:56 +00:00
|
|
|
|
void SbiDisas::VarDefOp( String& rText )
|
|
|
|
|
{
|
2008-06-24 15:01:06 +00:00
|
|
|
|
rText += rImg.GetString( (USHORT)(nOp1 & 0x7FFF) );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
rText.AppendAscii( "\t; " );
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// The Typ
|
2000-09-18 15:18:56 +00:00
|
|
|
|
nOp1 = nOp2;
|
|
|
|
|
TypeOp( rText );
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// Print variable: Offset and Typ
|
2000-09-18 15:18:56 +00:00
|
|
|
|
void SbiDisas::OffOp( String& rText )
|
|
|
|
|
{
|
2004-02-26 11:59:43 +00:00
|
|
|
|
rText += String::CreateFromInt32( nOp1 & 0x7FFF );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
rText.AppendAscii( "\t; " );
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// The type
|
2008-06-24 15:01:06 +00:00
|
|
|
|
UINT32 n = nOp1;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
nOp1 = nOp2;
|
|
|
|
|
TypeOp( rText );
|
|
|
|
|
if( n & 0x8000 )
|
|
|
|
|
rText.AppendAscii( ", Args" );
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// Data type
|
|
|
|
|
#ifdef HP9000 // TODO: remove this!
|
2000-09-18 15:18:56 +00:00
|
|
|
|
static char* SbiDisas_TypeOp_pTypes[13] = {
|
|
|
|
|
"Empty","Null","Integer","Long","Single","Double",
|
|
|
|
|
"Currency","Date","String","Object","Error","Boolean",
|
|
|
|
|
"Variant" };
|
|
|
|
|
#define pTypes SbiDisas_TypeOp_pTypes
|
|
|
|
|
#endif
|
|
|
|
|
void SbiDisas::TypeOp( String& rText )
|
|
|
|
|
{
|
|
|
|
|
// AB 19.1.96: Typ kann Flag f<>r BYVAL enthalten (StepARGTYP)
|
|
|
|
|
if( nOp1 & 0x8000 )
|
|
|
|
|
{
|
|
|
|
|
nOp1 &= 0x7FFF; // Flag wegfiltern
|
|
|
|
|
rText.AppendAscii( "BYVAL " );
|
|
|
|
|
}
|
|
|
|
|
if( nOp1 < 13 )
|
|
|
|
|
{
|
|
|
|
|
#ifndef HP9000
|
2006-06-19 16:38:48 +00:00
|
|
|
|
static char pTypes[][13] = {
|
2000-09-18 15:18:56 +00:00
|
|
|
|
"Empty","Null","Integer","Long","Single","Double",
|
|
|
|
|
"Currency","Date","String","Object","Error","Boolean",
|
|
|
|
|
"Variant" };
|
|
|
|
|
#endif
|
|
|
|
|
rText.AppendAscii( pTypes[ nOp1 ] );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rText.AppendAscii( "type " );
|
2008-06-24 15:01:06 +00:00
|
|
|
|
rText += (USHORT)nOp1;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#ifdef HP9000
|
|
|
|
|
#undef pTypes
|
|
|
|
|
#endif
|
|
|
|
|
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// TRUE-Label, condition Opcode
|
2000-09-18 15:18:56 +00:00
|
|
|
|
void SbiDisas::CaseOp( String& rText )
|
|
|
|
|
{
|
|
|
|
|
LblOp( rText );
|
|
|
|
|
rText += ',';
|
|
|
|
|
rText.AppendAscii( pOp1[ nOp2 - SbxEQ + _EQ ] );
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 00:18:20 +00:00
|
|
|
|
// Row, column
|
2000-09-18 15:18:56 +00:00
|
|
|
|
void SbiDisas::StmntOp( String& rText )
|
|
|
|
|
{
|
2003-03-18 15:28:40 +00:00
|
|
|
|
rText += String::CreateFromInt32( nOp1 );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
rText += ',';
|
2008-06-24 15:01:06 +00:00
|
|
|
|
UINT32 nCol = nOp2 & 0xFF;
|
|
|
|
|
UINT32 nFor = nOp2 / 0x100;
|
2003-03-18 15:28:40 +00:00
|
|
|
|
rText += String::CreateFromInt32( nCol );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
rText.AppendAscii( " (For-Level: " );
|
2003-03-18 15:28:40 +00:00
|
|
|
|
rText += String::CreateFromInt32( nFor );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
rText += ')';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// open mode, flags
|
|
|
|
|
void SbiDisas::StrmOp( String& rText )
|
|
|
|
|
{
|
|
|
|
|
char cBuf[ 10 ];
|
2008-06-24 15:01:06 +00:00
|
|
|
|
snprintf( cBuf, sizeof(cBuf), "%04" SAL_PRIXUINT32, nOp1 );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
rText.AppendAscii( cBuf );
|
|
|
|
|
if( nOp2 & SBSTRM_INPUT )
|
|
|
|
|
rText.AppendAscii( ", Input" );
|
|
|
|
|
if( nOp2 & SBSTRM_OUTPUT )
|
|
|
|
|
rText.AppendAscii( ", Output" );
|
|
|
|
|
if( nOp2 & SBSTRM_APPEND )
|
|
|
|
|
rText.AppendAscii( ", Append" );
|
|
|
|
|
if( nOp2 & SBSTRM_RANDOM )
|
|
|
|
|
rText.AppendAscii( ", Random" );
|
|
|
|
|
if( nOp2 & SBSTRM_BINARY )
|
|
|
|
|
rText.AppendAscii( ", Binary" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|