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? 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 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 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 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 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 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 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 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 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 498cdf0e10cSrcweir void SbiDisas::ImmOp( String& rText ) 499cdf0e10cSrcweir { 500cdf0e10cSrcweir rText += String::CreateFromInt32(nOp1); 501cdf0e10cSrcweir } 502cdf0e10cSrcweir 503cdf0e10cSrcweir // OnGoto Operand 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 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 520cdf0e10cSrcweir void SbiDisas::ReturnOp( String& rText ) 521cdf0e10cSrcweir { 522cdf0e10cSrcweir if( nOp1 ) 523cdf0e10cSrcweir LblOp( rText ); 524cdf0e10cSrcweir } 525cdf0e10cSrcweir 526cdf0e10cSrcweir // 0, 1 or Label 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 538cdf0e10cSrcweir void SbiDisas::PromptOp( String& rText ) 539cdf0e10cSrcweir { 540cdf0e10cSrcweir if( nOp1 ) 541cdf0e10cSrcweir rText.AppendAscii( "\"? \"" ); 542cdf0e10cSrcweir } 543cdf0e10cSrcweir 544cdf0e10cSrcweir // 0 or 1 545cdf0e10cSrcweir void SbiDisas::CloseOp( String& rText ) 546cdf0e10cSrcweir { 547cdf0e10cSrcweir rText.AppendAscii( nOp1 ? "Channel" : "All" ); 548cdf0e10cSrcweir } 549cdf0e10cSrcweir 550cdf0e10cSrcweir // Print character 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 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 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 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 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 645cdf0e10cSrcweir void SbiDisas::CaseOp( String& rText ) 646cdf0e10cSrcweir { 647cdf0e10cSrcweir LblOp( rText ); 648cdf0e10cSrcweir rText += ','; 649cdf0e10cSrcweir rText.AppendAscii( pOp1[ nOp2 - SbxEQ + _EQ ] ); 650cdf0e10cSrcweir } 651cdf0e10cSrcweir 652cdf0e10cSrcweir // Row, column 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 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 } 682cdf0e10cSrcweir 683cdf0e10cSrcweir 684