xref: /AOO41X/main/basic/source/classes/disas.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_basic.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <stdio.h>
32*cdf0e10cSrcweir #include <string.h>
33*cdf0e10cSrcweir #include <tools/stream.hxx>
34*cdf0e10cSrcweir #include <basic/sbx.hxx>
35*cdf0e10cSrcweir #include "sb.hxx"
36*cdf0e10cSrcweir #include "iosys.hxx"
37*cdf0e10cSrcweir #include "disas.hxx"
38*cdf0e10cSrcweir #include "sbtrace.hxx"
39*cdf0e10cSrcweir 
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir static const char* pOp1[] = {
42*cdf0e10cSrcweir 	"NOP",
43*cdf0e10cSrcweir 
44*cdf0e10cSrcweir 	// Operators
45*cdf0e10cSrcweir 	// the following operators have the same order as in
46*cdf0e10cSrcweir 	// enum SbxVarOp
47*cdf0e10cSrcweir 	"EXP", "MUL", "DIV", "MOD", "PLUS", "MINUS", "NEG",
48*cdf0e10cSrcweir 	"EQ", "NE", "LT", "GT", "LE", "GE",
49*cdf0e10cSrcweir 	"IDIV", "AND", "OR", "XOR", "EQV", "IMP", "NOT",
50*cdf0e10cSrcweir 	"CAT",
51*cdf0e10cSrcweir 	// End enum SbxVarOp
52*cdf0e10cSrcweir 	"LIKE", "IS",
53*cdf0e10cSrcweir 	// Load/Store
54*cdf0e10cSrcweir 	"ARGC",             // Create new Argv
55*cdf0e10cSrcweir 	"ARGV",             // TOS ==> current Argv
56*cdf0e10cSrcweir 	"INPUT",            // Input ==> TOS
57*cdf0e10cSrcweir 	"LINPUT",           // Line Input ==> TOS
58*cdf0e10cSrcweir 	"GET",              // get TOS
59*cdf0e10cSrcweir 	"SET",              // Save Object TOS ==> TOS-1
60*cdf0e10cSrcweir 	"PUT",              // TOS ==> TOS-1
61*cdf0e10cSrcweir 	"CONST",            // TOS ==> TOS-1, then ReadOnly
62*cdf0e10cSrcweir 	"DIM",              // DIM
63*cdf0e10cSrcweir 	"REDIM",            // REDIM
64*cdf0e10cSrcweir 	"REDIMP",           // REDIM PRESERVE
65*cdf0e10cSrcweir 	"ERASE",            // delete TOS
66*cdf0e10cSrcweir 	// Branch
67*cdf0e10cSrcweir 	"STOP",             // End of program
68*cdf0e10cSrcweir 	"INITFOR",          // FOR-Variable init
69*cdf0e10cSrcweir 	"NEXT",             // FOR-Variable increment
70*cdf0e10cSrcweir 	"CASE",             // Begin CASE
71*cdf0e10cSrcweir 	"ENDCASE",          // End CASE
72*cdf0e10cSrcweir 	"STDERR",           // Default error handling
73*cdf0e10cSrcweir 	"NOERROR",          // No error handling
74*cdf0e10cSrcweir 	"LEAVE",            // leave UP
75*cdf0e10cSrcweir 	// I/O
76*cdf0e10cSrcweir 	"CHANNEL",          // TOS = Channelnumber
77*cdf0e10cSrcweir 	"PRINT",            // print TOS
78*cdf0e10cSrcweir 	"PRINTF",           // print TOS in field
79*cdf0e10cSrcweir 	"WRITE",            // write TOS
80*cdf0e10cSrcweir 	"RENAME",           // Rename Tos+1 to Tos
81*cdf0e10cSrcweir 	"PROMPT",           // TOS = Prompt for Input
82*cdf0e10cSrcweir 	"RESTART",          // Define restart point
83*cdf0e10cSrcweir 	"STDIO",            // Switch to I/O channel 0
84*cdf0e10cSrcweir 	// Misc
85*cdf0e10cSrcweir 	"EMPTY",            // Empty statement to stack
86*cdf0e10cSrcweir 	"ERROR",            // TOS = error code
87*cdf0e10cSrcweir 	"LSET",             // Save object TOS ==> TOS-1
88*cdf0e10cSrcweir 	"RSET",             // Save object TOS ==> TOS-1 (TODO: Same as above?)
89*cdf0e10cSrcweir     "REDIMP_ERASE",
90*cdf0e10cSrcweir     "INITFOREACH",
91*cdf0e10cSrcweir 	"VBASET",
92*cdf0e10cSrcweir 	"ERASE_CLEAR",
93*cdf0e10cSrcweir 	"ARRAYACCESS",
94*cdf0e10cSrcweir 	"BYVAL"
95*cdf0e10cSrcweir };
96*cdf0e10cSrcweir 
97*cdf0e10cSrcweir static const char* pOp2[] = {
98*cdf0e10cSrcweir 	"NUMBER",            // Load a numeric constant (+ID)
99*cdf0e10cSrcweir 	"STRING",            // Load a string constant (+ID)
100*cdf0e10cSrcweir 	"CONSTANT",          // Immediate Load (+value)
101*cdf0e10cSrcweir 	"ARGN",              // Save named args in argv (+StringID)
102*cdf0e10cSrcweir 	"PAD",               // Pad String to defined length (+length)
103*cdf0e10cSrcweir 	// Branches
104*cdf0e10cSrcweir 	"JUMP",              // Jump to target (+Target)
105*cdf0e10cSrcweir 	"JUMP.T",            // evaluate TOS, conditional jump (+Target)
106*cdf0e10cSrcweir 	"JUMP.F",            // evaluate TOS, conditional jump (+Target)
107*cdf0e10cSrcweir 	"ONJUMP",            // evaluate TOS, jump into JUMP-table (+MaxVal)
108*cdf0e10cSrcweir 	"GOSUB",             // UP-Call (+Target)
109*cdf0e10cSrcweir 	"RETURN",            // UP-Return (+0 or Target)
110*cdf0e10cSrcweir 	"TESTFOR",           // Test FOR-Variable, increment (+Endlabel)
111*cdf0e10cSrcweir 	"CASETO",            // Tos+1 <= Case <= Tos, 2xremove (+Target)
112*cdf0e10cSrcweir 	"ERRHDL",            // Error-Handler (+Offset)
113*cdf0e10cSrcweir 	"RESUME",            // Resume after errors (+0 or 1 or Label)
114*cdf0e10cSrcweir 	// I/O
115*cdf0e10cSrcweir 	"CLOSE",             // (+channel/0)
116*cdf0e10cSrcweir 	"PRCHAR",            // (+char)
117*cdf0e10cSrcweir 	// Objects
118*cdf0e10cSrcweir 	"SETCLASS",          // Test Set + Classname (+StringId)
119*cdf0e10cSrcweir 	"TESTCLASS",         // Check TOS class (+StringId)
120*cdf0e10cSrcweir 	"LIB",               // Set Libname for Declare-Procs (+StringId)
121*cdf0e10cSrcweir 	// New since Beta 3 (TODO: Which Beta3?)
122*cdf0e10cSrcweir 	"BASED",             // TOS is incremted about BASE, push BASE before
123*cdf0e10cSrcweir 	"ARGTYP",            // Convert last parameter in argv (+Type)
124*cdf0e10cSrcweir 	"VBASETCLASS",
125*cdf0e10cSrcweir };
126*cdf0e10cSrcweir 
127*cdf0e10cSrcweir static const char* pOp3[] = {
128*cdf0e10cSrcweir 	// All opcodes with two operands
129*cdf0e10cSrcweir 	"RTL",              // Load from RTL (+StringID+Typ)
130*cdf0e10cSrcweir 	"FIND",             // Load (+StringID+Typ)
131*cdf0e10cSrcweir 	"ELEM",             // Load element (+StringID+Typ)
132*cdf0e10cSrcweir 	"PARAM",            // Parameter (+Offset+Typ)
133*cdf0e10cSrcweir 
134*cdf0e10cSrcweir     // Branching
135*cdf0e10cSrcweir 	"CALL",             // Call DECLARE method (+StringID+Typ)
136*cdf0e10cSrcweir 	"CALL.C",           // Call Cdecl-DECLARE method (+StringID+Typ)
137*cdf0e10cSrcweir 	"CASEIS",           // Case-Test (+Test-Opcode+False-Target)
138*cdf0e10cSrcweir 	"STMNT",            // Start of a statement (+Line+Col)
139*cdf0e10cSrcweir 
140*cdf0e10cSrcweir     // I/O
141*cdf0e10cSrcweir 	"OPEN",             // (+SvStreamFlags+Flags)
142*cdf0e10cSrcweir 
143*cdf0e10cSrcweir     // Objects and variables
144*cdf0e10cSrcweir 	"LOCAL",            // Local variables (+StringID+Typ)
145*cdf0e10cSrcweir 	"PUBLIC",           // Modul global var (+StringID+Typ)
146*cdf0e10cSrcweir 	"GLOBAL",           // Global var (+StringID+Typ)
147*cdf0e10cSrcweir 	"CREATE",           // Create object (+StringId+StringId)
148*cdf0e10cSrcweir 	"STATIC",           // Create static object (+StringId+StringId)
149*cdf0e10cSrcweir 	"TCREATE",          // Create User defined Object (+StringId+StringId)
150*cdf0e10cSrcweir 	"DCREATE",          // Create User defined Object-Array kreieren (+StringId+StringId)
151*cdf0e10cSrcweir     "GLOBAL_P",         // Define persistent global var (existing after basic restart)
152*cdf0e10cSrcweir                         // P=PERSIST (+StringID+Typ)
153*cdf0e10cSrcweir     "FIND_G",           // Searches for global var with special handling due to _GLOBAL_P
154*cdf0e10cSrcweir     "DCREATE_REDIMP",   // Change dimensions of a user defined Object-Array (+StringId+StringId)
155*cdf0e10cSrcweir     "FIND_CM",          // Search inside a class module (CM) to enable global search in time
156*cdf0e10cSrcweir     "PUBLIC_P",        	// Module global Variable (persisted between calls)(+StringID+Typ)
157*cdf0e10cSrcweir     "FIND_STATIC",     	// local static var lookup (+StringID+Typ)
158*cdf0e10cSrcweir };
159*cdf0e10cSrcweir 
160*cdf0e10cSrcweir static const char** pOps[3] = { pOp1, pOp2, pOp3 };
161*cdf0e10cSrcweir 
162*cdf0e10cSrcweir typedef void( SbiDisas::*Func )( String& );  // Processing routines
163*cdf0e10cSrcweir 
164*cdf0e10cSrcweir static const Func pOperand2[] = {
165*cdf0e10cSrcweir 	&SbiDisas::StrOp,	// Load a numeric constant (+ID)
166*cdf0e10cSrcweir 	&SbiDisas::StrOp,	// Load a string constant (+ID)
167*cdf0e10cSrcweir 	&SbiDisas::ImmOp,	// Immediate Load (+Wert)
168*cdf0e10cSrcweir 	&SbiDisas::StrOp,	// Save a named argument (+ID)
169*cdf0e10cSrcweir 	&SbiDisas::ImmOp,	// Strip String to fixed size (+length)
170*cdf0e10cSrcweir 
171*cdf0e10cSrcweir     // Branches
172*cdf0e10cSrcweir 	&SbiDisas::LblOp,	// Jump (+Target)
173*cdf0e10cSrcweir 	&SbiDisas::LblOp,	// eval TOS, conditional jump (+Target)
174*cdf0e10cSrcweir 	&SbiDisas::LblOp, 	// eval TOS, conditional jump (+Target)
175*cdf0e10cSrcweir 	&SbiDisas::OnOp,	// eval TOS, jump in JUMP table (+MaxVal)
176*cdf0e10cSrcweir 	&SbiDisas::LblOp,	// UP call (+Target)
177*cdf0e10cSrcweir 	&SbiDisas::ReturnOp,	// UP Return (+0 or Target)
178*cdf0e10cSrcweir 	&SbiDisas::LblOp,	// test FOR-Variable, increment (+Endlabel)
179*cdf0e10cSrcweir 	&SbiDisas::LblOp,	// Tos+1 <= Case <= Tos), 2xremove (+Target)
180*cdf0e10cSrcweir 	&SbiDisas::LblOp,	// Error handler (+Offset)
181*cdf0e10cSrcweir 	&SbiDisas::ResumeOp,	// Resume after errors (+0 or 1 or Label)
182*cdf0e10cSrcweir 
183*cdf0e10cSrcweir     // I/O
184*cdf0e10cSrcweir 	&SbiDisas::CloseOp,	// (+channel/0)
185*cdf0e10cSrcweir 	&SbiDisas::CharOp,	// (+char)
186*cdf0e10cSrcweir 
187*cdf0e10cSrcweir     // Objects
188*cdf0e10cSrcweir 	&SbiDisas::StrOp,   // Test classname (+StringId)
189*cdf0e10cSrcweir 	&SbiDisas::StrOp,   // TESTCLASS, Check TOS class (+StringId)
190*cdf0e10cSrcweir 	&SbiDisas::StrOp,   // Set libname for declare procs (+StringId)
191*cdf0e10cSrcweir 	&SbiDisas::ImmOp,   // TOS is incremented about BASE erhoeht, BASE pushed before
192*cdf0e10cSrcweir 	&SbiDisas::TypeOp,  // Convert last parameter to/in(?) argv (+Typ)
193*cdf0e10cSrcweir 	&SbiDisas::StrOp,   // VBASETCLASS (+StringId)
194*cdf0e10cSrcweir };
195*cdf0e10cSrcweir 
196*cdf0e10cSrcweir static const Func pOperand3[] = {
197*cdf0e10cSrcweir 	// All opcodes with two operands
198*cdf0e10cSrcweir 	&SbiDisas::VarOp,	// Load from RTL (+StringID+Typ)
199*cdf0e10cSrcweir 	&SbiDisas::VarOp,	// Load (+StringID+Typ)
200*cdf0e10cSrcweir 	&SbiDisas::VarOp,	// Load Element (+StringID+Typ)
201*cdf0e10cSrcweir 	&SbiDisas::OffOp,	// Parameter (+Offset+Typ)
202*cdf0e10cSrcweir 
203*cdf0e10cSrcweir 	// Branch
204*cdf0e10cSrcweir 	&SbiDisas::VarOp,	// Call DECLARE-Method (+StringID+Typ)
205*cdf0e10cSrcweir 	&SbiDisas::VarOp,	// Call CDecl-DECLARE-Methode (+StringID+Typ)
206*cdf0e10cSrcweir 	&SbiDisas::CaseOp,	// Case-Test (+Test-Opcode+False-Target)
207*cdf0e10cSrcweir 	&SbiDisas::StmntOp,	// Statement (+Row+Column)
208*cdf0e10cSrcweir 
209*cdf0e10cSrcweir 	// I/O
210*cdf0e10cSrcweir 	&SbiDisas::StrmOp,	// (+SvStreamFlags+Flags)
211*cdf0e10cSrcweir 
212*cdf0e10cSrcweir 	// Objects
213*cdf0e10cSrcweir 	&SbiDisas::VarDefOp,   // Define local var (+StringID+Typ)
214*cdf0e10cSrcweir 	&SbiDisas::VarDefOp,   // Define Module global var (+StringID+Typ)
215*cdf0e10cSrcweir 	&SbiDisas::VarDefOp,   // Define global var (+StringID+Typ)
216*cdf0e10cSrcweir 	&SbiDisas::Str2Op,     // Create object (+StringId+StringId)
217*cdf0e10cSrcweir 	&SbiDisas::VarDefOp,   // Define static object (+StringID+Typ)
218*cdf0e10cSrcweir 	&SbiDisas::Str2Op,     // Create User defined Object (+StringId+StringId)
219*cdf0e10cSrcweir 	&SbiDisas::Str2Op,     // Create User defined Object-Array (+StringId+StringId)
220*cdf0e10cSrcweir 	&SbiDisas::VarDefOp,   // Define persistent global var P=PERSIST (+StringID+Typ)
221*cdf0e10cSrcweir     &SbiDisas::VarOp,    // Searches for global var with special handling due to  _GLOBAL_P
222*cdf0e10cSrcweir 	&SbiDisas::Str2Op,     // Redimensionate User defined Object-Array (+StringId+StringId)
223*cdf0e10cSrcweir 	&SbiDisas::VarOp,	 // FIND_CM
224*cdf0e10cSrcweir 	&SbiDisas::VarDefOp, // PUBLIC_P
225*cdf0e10cSrcweir 	&SbiDisas::VarOp,	 // FIND_STATIC
226*cdf0e10cSrcweir };
227*cdf0e10cSrcweir 
228*cdf0e10cSrcweir // TODO: Why as method? Isn't a simple define sufficient?
229*cdf0e10cSrcweir static const char* _crlf()
230*cdf0e10cSrcweir {
231*cdf0e10cSrcweir #if defined (UNX) || defined( PM2 )
232*cdf0e10cSrcweir 	return "\n";
233*cdf0e10cSrcweir #else
234*cdf0e10cSrcweir 	return "\r\n";
235*cdf0e10cSrcweir #endif
236*cdf0e10cSrcweir }
237*cdf0e10cSrcweir 
238*cdf0e10cSrcweir // This method exists because we want to load the file as own segment
239*cdf0e10cSrcweir sal_Bool SbModule::Disassemble( String& rText )
240*cdf0e10cSrcweir {
241*cdf0e10cSrcweir 	rText.Erase();
242*cdf0e10cSrcweir 	if( pImage )
243*cdf0e10cSrcweir 	{
244*cdf0e10cSrcweir 		SbiDisas aDisas( this, pImage );
245*cdf0e10cSrcweir 		aDisas.Disas( rText );
246*cdf0e10cSrcweir 	}
247*cdf0e10cSrcweir 	return sal_Bool( rText.Len() != 0 );
248*cdf0e10cSrcweir }
249*cdf0e10cSrcweir 
250*cdf0e10cSrcweir SbiDisas::SbiDisas( SbModule* p, const SbiImage* q ) : rImg( *q ), pMod( p )
251*cdf0e10cSrcweir {
252*cdf0e10cSrcweir 	memset( cLabels, 0, 8192 );
253*cdf0e10cSrcweir 	nLine = 0;
254*cdf0e10cSrcweir 	nOff = 0;
255*cdf0e10cSrcweir 	nPC = 0;
256*cdf0e10cSrcweir 	nOp1 = nOp2 = nParts = 0;
257*cdf0e10cSrcweir 	eOp = _NOP;
258*cdf0e10cSrcweir 	// Set Label-Bits
259*cdf0e10cSrcweir 	nOff = 0;
260*cdf0e10cSrcweir 	while( Fetch() )
261*cdf0e10cSrcweir 	{
262*cdf0e10cSrcweir 		switch( eOp )
263*cdf0e10cSrcweir 		{
264*cdf0e10cSrcweir 			case _RESUME: if( nOp1 <= 1 ) break;
265*cdf0e10cSrcweir 			case _RETURN: if( !nOp1 ) break;
266*cdf0e10cSrcweir 			case _JUMP:
267*cdf0e10cSrcweir 			case _JUMPT:
268*cdf0e10cSrcweir 			case _JUMPF:
269*cdf0e10cSrcweir 			case _GOSUB:
270*cdf0e10cSrcweir 			case _TESTFOR:
271*cdf0e10cSrcweir 			case _CASEIS:
272*cdf0e10cSrcweir 			case _CASETO:
273*cdf0e10cSrcweir 			case _ERRHDL:
274*cdf0e10cSrcweir                 cLabels[ (nOp1 & 0xffff) >> 3 ] |= ( 1 << ( nOp1 & 7 ) );
275*cdf0e10cSrcweir                 break;
276*cdf0e10cSrcweir 			default: break;
277*cdf0e10cSrcweir 		}
278*cdf0e10cSrcweir 	}
279*cdf0e10cSrcweir 	nOff = 0;
280*cdf0e10cSrcweir 	// Add the publics
281*cdf0e10cSrcweir 	for( sal_uInt16 i = 0; i < pMod->GetMethods()->Count(); i++ )
282*cdf0e10cSrcweir 	{
283*cdf0e10cSrcweir 		SbMethod* pMeth = PTR_CAST(SbMethod,pMod->GetMethods()->Get( i ));
284*cdf0e10cSrcweir 		if( pMeth )
285*cdf0e10cSrcweir 		{
286*cdf0e10cSrcweir 			sal_uInt16 nPos = (sal_uInt16) (pMeth->GetId());
287*cdf0e10cSrcweir 			cLabels[ nPos >> 3 ] |= ( 1 << ( nPos & 7 ) );
288*cdf0e10cSrcweir 		}
289*cdf0e10cSrcweir 	}
290*cdf0e10cSrcweir }
291*cdf0e10cSrcweir 
292*cdf0e10cSrcweir // Read current opcode
293*cdf0e10cSrcweir sal_Bool SbiDisas::Fetch()
294*cdf0e10cSrcweir {
295*cdf0e10cSrcweir 	nPC = nOff;
296*cdf0e10cSrcweir 	if( nOff >= rImg.GetCodeSize() )
297*cdf0e10cSrcweir 		return sal_False;
298*cdf0e10cSrcweir 	const unsigned char* p = (const unsigned char*)( rImg.GetCode() + nOff );
299*cdf0e10cSrcweir 	eOp = (SbiOpcode) ( *p++ & 0xFF );
300*cdf0e10cSrcweir 	if( eOp <= SbOP0_END )
301*cdf0e10cSrcweir 	{
302*cdf0e10cSrcweir 		nOp1 = nOp2 = 0;
303*cdf0e10cSrcweir 		nParts = 1;
304*cdf0e10cSrcweir 		nOff++;
305*cdf0e10cSrcweir 		return sal_True;
306*cdf0e10cSrcweir 	}
307*cdf0e10cSrcweir 	else if( eOp <= SbOP1_END )
308*cdf0e10cSrcweir 	{
309*cdf0e10cSrcweir 		nOff += 5;
310*cdf0e10cSrcweir 		if( nOff > rImg.GetCodeSize() )
311*cdf0e10cSrcweir 			return sal_False;
312*cdf0e10cSrcweir 		nOp1 = *p++; nOp1 |= *p++ << 8; nOp1 |= *p++ << 16; nOp1 |= *p++ << 24;
313*cdf0e10cSrcweir 		nParts = 2;
314*cdf0e10cSrcweir 		return sal_True;
315*cdf0e10cSrcweir 	}
316*cdf0e10cSrcweir 	else if( eOp <= SbOP2_END )
317*cdf0e10cSrcweir 	{
318*cdf0e10cSrcweir 		nOff += 9;
319*cdf0e10cSrcweir 		if( nOff > rImg.GetCodeSize() )
320*cdf0e10cSrcweir 			return sal_False;
321*cdf0e10cSrcweir 		nOp1 = *p++; nOp1 |= *p++ << 8; nOp1 |= *p++ << 16; nOp1 |= *p++ << 24;
322*cdf0e10cSrcweir 		nOp2 = *p++; nOp2 |= *p++ << 8; nOp2 |= *p++ << 16; nOp2 |= *p++ << 24;
323*cdf0e10cSrcweir 		nParts = 3;
324*cdf0e10cSrcweir 		return sal_True;
325*cdf0e10cSrcweir 	}
326*cdf0e10cSrcweir 	else
327*cdf0e10cSrcweir 		return sal_False;
328*cdf0e10cSrcweir }
329*cdf0e10cSrcweir 
330*cdf0e10cSrcweir void SbiDisas::Disas( SvStream& r )
331*cdf0e10cSrcweir {
332*cdf0e10cSrcweir 	String aText;
333*cdf0e10cSrcweir 	nOff = 0;
334*cdf0e10cSrcweir 	while( DisasLine( aText ) )
335*cdf0e10cSrcweir 	{
336*cdf0e10cSrcweir 		ByteString aByteText( aText, gsl_getSystemTextEncoding() );
337*cdf0e10cSrcweir 		r.WriteLine( aByteText );
338*cdf0e10cSrcweir 	}
339*cdf0e10cSrcweir }
340*cdf0e10cSrcweir 
341*cdf0e10cSrcweir void SbiDisas::Disas( String& r )
342*cdf0e10cSrcweir {
343*cdf0e10cSrcweir 	r.Erase();
344*cdf0e10cSrcweir 	String aText;
345*cdf0e10cSrcweir 	nOff = 0;
346*cdf0e10cSrcweir 	while( DisasLine( aText ) )
347*cdf0e10cSrcweir 	{
348*cdf0e10cSrcweir 		r += aText;
349*cdf0e10cSrcweir 		r.AppendAscii( _crlf() );
350*cdf0e10cSrcweir 	}
351*cdf0e10cSrcweir 	aText.ConvertLineEnd();
352*cdf0e10cSrcweir }
353*cdf0e10cSrcweir 
354*cdf0e10cSrcweir sal_Bool SbiDisas::DisasLine( String& rText )
355*cdf0e10cSrcweir {
356*cdf0e10cSrcweir 	char cBuf[ 100 ];
357*cdf0e10cSrcweir 	const char* pMask[] = {
358*cdf0e10cSrcweir 		"%08" SAL_PRIXUINT32 "                            ",
359*cdf0e10cSrcweir 		"%08" SAL_PRIXUINT32 " %02X                   ",
360*cdf0e10cSrcweir 		"%08" SAL_PRIXUINT32 " %02X %08X          ",
361*cdf0e10cSrcweir 		"%08" SAL_PRIXUINT32 " %02X %08X %08X " };
362*cdf0e10cSrcweir 	rText.Erase();
363*cdf0e10cSrcweir 	if( !Fetch() )
364*cdf0e10cSrcweir 		return sal_False;
365*cdf0e10cSrcweir 
366*cdf0e10cSrcweir #ifdef DBG_TRACE_BASIC
367*cdf0e10cSrcweir 	String aTraceStr_STMNT;
368*cdf0e10cSrcweir #endif
369*cdf0e10cSrcweir 
370*cdf0e10cSrcweir 	// New line?
371*cdf0e10cSrcweir 	if( eOp == _STMNT && nOp1 != nLine )
372*cdf0e10cSrcweir 	{
373*cdf0e10cSrcweir         // Find line
374*cdf0e10cSrcweir         String aSource = rImg.aOUSource;
375*cdf0e10cSrcweir 		nLine = nOp1;
376*cdf0e10cSrcweir 		sal_uInt16 n = 0;
377*cdf0e10cSrcweir 		sal_uInt16 l = (sal_uInt16)nLine;
378*cdf0e10cSrcweir 		while( --l ) {
379*cdf0e10cSrcweir 			n = aSource.SearchAscii( "\n", n );
380*cdf0e10cSrcweir 			if( n == STRING_NOTFOUND ) break;
381*cdf0e10cSrcweir 			else n++;
382*cdf0e10cSrcweir 		}
383*cdf0e10cSrcweir 		// Show position
384*cdf0e10cSrcweir 		if( n != STRING_NOTFOUND )
385*cdf0e10cSrcweir 		{
386*cdf0e10cSrcweir 			sal_uInt16 n2 = aSource.SearchAscii( "\n", n );
387*cdf0e10cSrcweir 			if( n2 == STRING_NOTFOUND ) n2 = aSource.Len() - n;
388*cdf0e10cSrcweir 			String s( aSource.Copy( n, n2 - n + 1 ) );
389*cdf0e10cSrcweir 			sal_Bool bDone;
390*cdf0e10cSrcweir 			do {
391*cdf0e10cSrcweir 				bDone = sal_True;
392*cdf0e10cSrcweir 				n = s.Search( '\r' );
393*cdf0e10cSrcweir 				if( n != STRING_NOTFOUND ) bDone = sal_False, s.Erase( n, 1 );
394*cdf0e10cSrcweir 				n = s.Search( '\n' );
395*cdf0e10cSrcweir 				if( n != STRING_NOTFOUND ) bDone = sal_False, s.Erase( n, 1 );
396*cdf0e10cSrcweir 			} while( !bDone );
397*cdf0e10cSrcweir //          snprintf( cBuf, sizeof(cBuf), pMask[ 0 ], nPC );
398*cdf0e10cSrcweir //			rText += cBuf;
399*cdf0e10cSrcweir 			rText.AppendAscii( "; " );
400*cdf0e10cSrcweir 			rText += s;
401*cdf0e10cSrcweir 			rText.AppendAscii( _crlf() );
402*cdf0e10cSrcweir 
403*cdf0e10cSrcweir #ifdef DBG_TRACE_BASIC
404*cdf0e10cSrcweir 			aTraceStr_STMNT = s;
405*cdf0e10cSrcweir #endif
406*cdf0e10cSrcweir 		}
407*cdf0e10cSrcweir 	}
408*cdf0e10cSrcweir 
409*cdf0e10cSrcweir 	// Label?
410*cdf0e10cSrcweir 	const char* p = "";
411*cdf0e10cSrcweir 	if( cLabels[ nPC >> 3 ] & ( 1 << ( nPC & 7 ) ) )
412*cdf0e10cSrcweir 	{
413*cdf0e10cSrcweir 		// Public?
414*cdf0e10cSrcweir 		ByteString aByteMethName;
415*cdf0e10cSrcweir 		for( sal_uInt16 i = 0; i < pMod->GetMethods()->Count(); i++ )
416*cdf0e10cSrcweir 		{
417*cdf0e10cSrcweir 			SbMethod* pMeth = PTR_CAST(SbMethod,pMod->GetMethods()->Get( i ));
418*cdf0e10cSrcweir 			if( pMeth )
419*cdf0e10cSrcweir 			{
420*cdf0e10cSrcweir 				aByteMethName = ByteString( pMeth->GetName(), gsl_getSystemTextEncoding() );
421*cdf0e10cSrcweir 				if( pMeth->GetId() == nPC )
422*cdf0e10cSrcweir 				{
423*cdf0e10cSrcweir 					p = aByteMethName.GetBuffer();
424*cdf0e10cSrcweir 					break;
425*cdf0e10cSrcweir 				}
426*cdf0e10cSrcweir 				if( pMeth->GetId() >= nPC )
427*cdf0e10cSrcweir 					break;
428*cdf0e10cSrcweir 			}
429*cdf0e10cSrcweir 		}
430*cdf0e10cSrcweir         snprintf( cBuf, sizeof(cBuf), pMask[ 0 ], nPC );
431*cdf0e10cSrcweir 		rText.AppendAscii( cBuf );
432*cdf0e10cSrcweir 		if( p && *p )
433*cdf0e10cSrcweir 		{
434*cdf0e10cSrcweir 			rText.AppendAscii( p );
435*cdf0e10cSrcweir 		}
436*cdf0e10cSrcweir 		else
437*cdf0e10cSrcweir 		{
438*cdf0e10cSrcweir             // fix warning (now error) for "Lbl%04lX" format
439*cdf0e10cSrcweir   			snprintf( cBuf, sizeof(cBuf), "Lbl%08" SAL_PRIXUINT32, nPC );
440*cdf0e10cSrcweir 			rText.AppendAscii( cBuf );
441*cdf0e10cSrcweir 		}
442*cdf0e10cSrcweir 		rText += ':';
443*cdf0e10cSrcweir 		rText.AppendAscii( _crlf() );
444*cdf0e10cSrcweir 	}
445*cdf0e10cSrcweir     snprintf( cBuf, sizeof(cBuf), pMask[ nParts ], nPC, (sal_uInt16) eOp, nOp1, nOp2 );
446*cdf0e10cSrcweir 
447*cdf0e10cSrcweir 	String aPCodeStr;
448*cdf0e10cSrcweir 	aPCodeStr.AppendAscii( cBuf );
449*cdf0e10cSrcweir 	int n = eOp;
450*cdf0e10cSrcweir 	if( eOp >= SbOP2_START )
451*cdf0e10cSrcweir 		n -= SbOP2_START;
452*cdf0e10cSrcweir 	else if( eOp >= SbOP1_START )
453*cdf0e10cSrcweir 		n -= SbOP1_START;
454*cdf0e10cSrcweir 	aPCodeStr += '\t';
455*cdf0e10cSrcweir 	aPCodeStr.AppendAscii( pOps[ nParts-1 ][ n ] );
456*cdf0e10cSrcweir 	aPCodeStr += '\t';
457*cdf0e10cSrcweir 	switch( nParts )
458*cdf0e10cSrcweir 	{
459*cdf0e10cSrcweir 		case 2: (this->*( pOperand2[ n ] ) )( aPCodeStr ); break;
460*cdf0e10cSrcweir 		case 3: (this->*( pOperand3[ n ] ) )( aPCodeStr ); break;
461*cdf0e10cSrcweir 	}
462*cdf0e10cSrcweir 
463*cdf0e10cSrcweir 	rText += aPCodeStr;
464*cdf0e10cSrcweir 
465*cdf0e10cSrcweir #ifdef DBG_TRACE_BASIC
466*cdf0e10cSrcweir 	dbg_RegisterTraceTextForPC( pMod, nPC, aTraceStr_STMNT, aPCodeStr );
467*cdf0e10cSrcweir #endif
468*cdf0e10cSrcweir 
469*cdf0e10cSrcweir 	return sal_True;
470*cdf0e10cSrcweir }
471*cdf0e10cSrcweir 
472*cdf0e10cSrcweir // Read from StringPool
473*cdf0e10cSrcweir void SbiDisas::StrOp( String& rText )
474*cdf0e10cSrcweir {
475*cdf0e10cSrcweir 	String aStr = rImg.GetString( (sal_uInt16)nOp1 );
476*cdf0e10cSrcweir 	ByteString aByteString( aStr, RTL_TEXTENCODING_ASCII_US );
477*cdf0e10cSrcweir 	const char* p = aByteString.GetBuffer();
478*cdf0e10cSrcweir 	if( p )
479*cdf0e10cSrcweir 	{
480*cdf0e10cSrcweir 		rText += '"';
481*cdf0e10cSrcweir 		rText.AppendAscii( p );
482*cdf0e10cSrcweir 		rText += '"';
483*cdf0e10cSrcweir 	}
484*cdf0e10cSrcweir 	else
485*cdf0e10cSrcweir 	{
486*cdf0e10cSrcweir 		rText.AppendAscii( "?String? " );
487*cdf0e10cSrcweir 		rText += (sal_uInt16)nOp1;
488*cdf0e10cSrcweir 	}
489*cdf0e10cSrcweir }
490*cdf0e10cSrcweir 
491*cdf0e10cSrcweir void SbiDisas::Str2Op( String& rText )
492*cdf0e10cSrcweir {
493*cdf0e10cSrcweir 	StrOp( rText );
494*cdf0e10cSrcweir 	rText += ',';
495*cdf0e10cSrcweir 	String s;
496*cdf0e10cSrcweir 	nOp1 = nOp2;
497*cdf0e10cSrcweir 	StrOp( s );
498*cdf0e10cSrcweir 	rText += s;
499*cdf0e10cSrcweir }
500*cdf0e10cSrcweir 
501*cdf0e10cSrcweir // Immediate Operand
502*cdf0e10cSrcweir void SbiDisas::ImmOp( String& rText )
503*cdf0e10cSrcweir {
504*cdf0e10cSrcweir 	rText += String::CreateFromInt32(nOp1);
505*cdf0e10cSrcweir }
506*cdf0e10cSrcweir 
507*cdf0e10cSrcweir // OnGoto Operand
508*cdf0e10cSrcweir void SbiDisas::OnOp( String& rText )
509*cdf0e10cSrcweir {
510*cdf0e10cSrcweir 	rText += String::CreateFromInt32(nOp1 & 0x7FFF);
511*cdf0e10cSrcweir 	if( nOp1 & 0x800 )
512*cdf0e10cSrcweir 		rText.AppendAscii( "\t; Gosub" );
513*cdf0e10cSrcweir }
514*cdf0e10cSrcweir 
515*cdf0e10cSrcweir // Label
516*cdf0e10cSrcweir void SbiDisas::LblOp( String& rText )
517*cdf0e10cSrcweir {
518*cdf0e10cSrcweir 	char cBuf[ 10 ];
519*cdf0e10cSrcweir     snprintf( cBuf, sizeof(cBuf), "Lbl%04" SAL_PRIXUINT32, nOp1 );
520*cdf0e10cSrcweir 	rText.AppendAscii( cBuf );
521*cdf0e10cSrcweir }
522*cdf0e10cSrcweir 
523*cdf0e10cSrcweir // 0 or Label
524*cdf0e10cSrcweir void SbiDisas::ReturnOp( String& rText )
525*cdf0e10cSrcweir {
526*cdf0e10cSrcweir 	if( nOp1 )
527*cdf0e10cSrcweir 		LblOp( rText );
528*cdf0e10cSrcweir }
529*cdf0e10cSrcweir 
530*cdf0e10cSrcweir // 0, 1 or Label
531*cdf0e10cSrcweir void SbiDisas::ResumeOp( String& rText )
532*cdf0e10cSrcweir {
533*cdf0e10cSrcweir 	switch( nOp1 )
534*cdf0e10cSrcweir 	{
535*cdf0e10cSrcweir 		case 1: rText.AppendAscii( "NEXT" ); break;
536*cdf0e10cSrcweir 		case 2: LblOp( rText );
537*cdf0e10cSrcweir 	}
538*cdf0e10cSrcweir }
539*cdf0e10cSrcweir 
540*cdf0e10cSrcweir // print Prompt
541*cdf0e10cSrcweir // sal_False/TRUE
542*cdf0e10cSrcweir void SbiDisas::PromptOp( String& rText )
543*cdf0e10cSrcweir {
544*cdf0e10cSrcweir 	if( nOp1 )
545*cdf0e10cSrcweir 		rText.AppendAscii( "\"? \"" );
546*cdf0e10cSrcweir }
547*cdf0e10cSrcweir 
548*cdf0e10cSrcweir // 0 or 1
549*cdf0e10cSrcweir void SbiDisas::CloseOp( String& rText )
550*cdf0e10cSrcweir {
551*cdf0e10cSrcweir 	rText.AppendAscii( nOp1 ? "Channel" : "All" );
552*cdf0e10cSrcweir }
553*cdf0e10cSrcweir 
554*cdf0e10cSrcweir // Print character
555*cdf0e10cSrcweir void SbiDisas::CharOp( String& rText )
556*cdf0e10cSrcweir {
557*cdf0e10cSrcweir 	const char* p = NULL;
558*cdf0e10cSrcweir 	switch( nOp1 )
559*cdf0e10cSrcweir 	{
560*cdf0e10cSrcweir 		case  7: p = "'\\a'"; break;
561*cdf0e10cSrcweir 		case  9: p = "'\\t'"; break;
562*cdf0e10cSrcweir 		case 10: p = "'\\n'"; break;
563*cdf0e10cSrcweir 		case 12: p = "'\\f'"; break;
564*cdf0e10cSrcweir 		case 13: p = "'\\r'"; break;
565*cdf0e10cSrcweir 	}
566*cdf0e10cSrcweir 	if( p ) rText.AppendAscii( p );
567*cdf0e10cSrcweir 	else if( nOp1 >= ' ' )
568*cdf0e10cSrcweir 		rText += '\'',
569*cdf0e10cSrcweir 		rText += (char) nOp1,
570*cdf0e10cSrcweir 		rText += '\'';
571*cdf0e10cSrcweir 	else
572*cdf0e10cSrcweir 		rText.AppendAscii( "char " ),
573*cdf0e10cSrcweir 		rText += (sal_uInt16)nOp1;
574*cdf0e10cSrcweir }
575*cdf0e10cSrcweir 
576*cdf0e10cSrcweir // Print var: String-ID and type
577*cdf0e10cSrcweir void SbiDisas::VarOp( String& rText )
578*cdf0e10cSrcweir {
579*cdf0e10cSrcweir 	rText += rImg.GetString( (sal_uInt16)(nOp1 & 0x7FFF) );
580*cdf0e10cSrcweir 	rText.AppendAscii( "\t; " );
581*cdf0e10cSrcweir     // The type
582*cdf0e10cSrcweir 	sal_uInt32 n = nOp1;
583*cdf0e10cSrcweir 	nOp1 = nOp2;
584*cdf0e10cSrcweir 	TypeOp( rText );
585*cdf0e10cSrcweir 	if( n & 0x8000 )
586*cdf0e10cSrcweir 		rText.AppendAscii( ", Args" );
587*cdf0e10cSrcweir }
588*cdf0e10cSrcweir 
589*cdf0e10cSrcweir // Define variable: String-ID and type
590*cdf0e10cSrcweir void SbiDisas::VarDefOp( String& rText )
591*cdf0e10cSrcweir {
592*cdf0e10cSrcweir 	rText += rImg.GetString( (sal_uInt16)(nOp1 & 0x7FFF) );
593*cdf0e10cSrcweir 	rText.AppendAscii( "\t; " );
594*cdf0e10cSrcweir     // The Typ
595*cdf0e10cSrcweir 	nOp1 = nOp2;
596*cdf0e10cSrcweir 	TypeOp( rText );
597*cdf0e10cSrcweir }
598*cdf0e10cSrcweir 
599*cdf0e10cSrcweir // Print variable: Offset and Typ
600*cdf0e10cSrcweir void SbiDisas::OffOp( String& rText )
601*cdf0e10cSrcweir {
602*cdf0e10cSrcweir 	rText += String::CreateFromInt32( nOp1 & 0x7FFF );
603*cdf0e10cSrcweir 	rText.AppendAscii( "\t; " );
604*cdf0e10cSrcweir 	// The type
605*cdf0e10cSrcweir 	sal_uInt32 n = nOp1;
606*cdf0e10cSrcweir 	nOp1 = nOp2;
607*cdf0e10cSrcweir 	TypeOp( rText );
608*cdf0e10cSrcweir 	if( n & 0x8000 )
609*cdf0e10cSrcweir 		rText.AppendAscii( ", Args" );
610*cdf0e10cSrcweir }
611*cdf0e10cSrcweir 
612*cdf0e10cSrcweir // Data type
613*cdf0e10cSrcweir #ifdef HP9000 // TODO: remove this!
614*cdf0e10cSrcweir static char* SbiDisas_TypeOp_pTypes[13] = {
615*cdf0e10cSrcweir 	"Empty","Null","Integer","Long","Single","Double",
616*cdf0e10cSrcweir 	"Currency","Date","String","Object","Error","Boolean",
617*cdf0e10cSrcweir 	"Variant" };
618*cdf0e10cSrcweir #define pTypes SbiDisas_TypeOp_pTypes
619*cdf0e10cSrcweir #endif
620*cdf0e10cSrcweir void SbiDisas::TypeOp( String& rText )
621*cdf0e10cSrcweir {
622*cdf0e10cSrcweir 	// AB 19.1.96: Typ kann Flag f�r BYVAL enthalten (StepARGTYP)
623*cdf0e10cSrcweir 	if( nOp1 & 0x8000 )
624*cdf0e10cSrcweir 	{
625*cdf0e10cSrcweir 		nOp1 &= 0x7FFF;		// Flag wegfiltern
626*cdf0e10cSrcweir 		rText.AppendAscii( "BYVAL " );
627*cdf0e10cSrcweir 	}
628*cdf0e10cSrcweir 	if( nOp1 < 13 )
629*cdf0e10cSrcweir 	{
630*cdf0e10cSrcweir #ifndef HP9000
631*cdf0e10cSrcweir 		static char pTypes[][13] = {
632*cdf0e10cSrcweir 			"Empty","Null","Integer","Long","Single","Double",
633*cdf0e10cSrcweir 			"Currency","Date","String","Object","Error","Boolean",
634*cdf0e10cSrcweir 			"Variant" };
635*cdf0e10cSrcweir #endif
636*cdf0e10cSrcweir 		rText.AppendAscii( pTypes[ nOp1 ] );
637*cdf0e10cSrcweir 	}
638*cdf0e10cSrcweir 	else
639*cdf0e10cSrcweir 	{
640*cdf0e10cSrcweir 		rText.AppendAscii( "type " );
641*cdf0e10cSrcweir 		rText += (sal_uInt16)nOp1;
642*cdf0e10cSrcweir 	}
643*cdf0e10cSrcweir }
644*cdf0e10cSrcweir #ifdef HP9000
645*cdf0e10cSrcweir #undef pTypes
646*cdf0e10cSrcweir #endif
647*cdf0e10cSrcweir 
648*cdf0e10cSrcweir // sal_True-Label, condition Opcode
649*cdf0e10cSrcweir void SbiDisas::CaseOp( String& rText )
650*cdf0e10cSrcweir {
651*cdf0e10cSrcweir 	LblOp( rText );
652*cdf0e10cSrcweir 	rText += ',';
653*cdf0e10cSrcweir 	rText.AppendAscii( pOp1[ nOp2 - SbxEQ + _EQ ] );
654*cdf0e10cSrcweir }
655*cdf0e10cSrcweir 
656*cdf0e10cSrcweir // Row, column
657*cdf0e10cSrcweir void SbiDisas::StmntOp( String& rText )
658*cdf0e10cSrcweir {
659*cdf0e10cSrcweir 	rText += String::CreateFromInt32( nOp1 );
660*cdf0e10cSrcweir 	rText += ',';
661*cdf0e10cSrcweir 	sal_uInt32 nCol = nOp2 & 0xFF;
662*cdf0e10cSrcweir 	sal_uInt32 nFor = nOp2 / 0x100;
663*cdf0e10cSrcweir     rText += String::CreateFromInt32( nCol );
664*cdf0e10cSrcweir 	rText.AppendAscii( " (For-Level: " );
665*cdf0e10cSrcweir 	rText += String::CreateFromInt32( nFor );
666*cdf0e10cSrcweir 	rText += ')';
667*cdf0e10cSrcweir }
668*cdf0e10cSrcweir 
669*cdf0e10cSrcweir // open mode, flags
670*cdf0e10cSrcweir void SbiDisas::StrmOp( String& rText )
671*cdf0e10cSrcweir {
672*cdf0e10cSrcweir 	char cBuf[ 10 ];
673*cdf0e10cSrcweir     snprintf( cBuf, sizeof(cBuf), "%04" SAL_PRIXUINT32, nOp1 );
674*cdf0e10cSrcweir 	rText.AppendAscii( cBuf );
675*cdf0e10cSrcweir 	if( nOp2 & SBSTRM_INPUT )
676*cdf0e10cSrcweir 		rText.AppendAscii( ", Input" );
677*cdf0e10cSrcweir 	if( nOp2 & SBSTRM_OUTPUT )
678*cdf0e10cSrcweir 		rText.AppendAscii( ", Output" );
679*cdf0e10cSrcweir 	if( nOp2 & SBSTRM_APPEND )
680*cdf0e10cSrcweir 		rText.AppendAscii( ", Append" );
681*cdf0e10cSrcweir 	if( nOp2 & SBSTRM_RANDOM )
682*cdf0e10cSrcweir 		rText.AppendAscii( ", Random" );
683*cdf0e10cSrcweir 	if( nOp2 & SBSTRM_BINARY )
684*cdf0e10cSrcweir 		rText.AppendAscii( ", Binary" );
685*cdf0e10cSrcweir }
686*cdf0e10cSrcweir 
687*cdf0e10cSrcweir 
688