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