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