| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_basic.hxx" |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include <tools/stream.hxx> |
| #include <basic/sbx.hxx> |
| #include "sb.hxx" |
| #include "iosys.hxx" |
| #include "disas.hxx" |
| #include "sbtrace.hxx" |
| |
| |
| static const char* pOp1[] = { |
| "NOP", |
| |
| // Operators |
| // the following operators have the same order as in |
| // enum SbxVarOp |
| "EXP", "MUL", "DIV", "MOD", "PLUS", "MINUS", "NEG", |
| "EQ", "NE", "LT", "GT", "LE", "GE", |
| "IDIV", "AND", "OR", "XOR", "EQV", "IMP", "NOT", |
| "CAT", |
| // End enum SbxVarOp |
| "LIKE", "IS", |
| // Load/Store |
| "ARGC", // Create new Argv |
| "ARGV", // TOS ==> current Argv |
| "INPUT", // Input ==> TOS |
| "LINPUT", // Line Input ==> TOS |
| "GET", // get TOS |
| "SET", // Save Object TOS ==> TOS-1 |
| "PUT", // TOS ==> TOS-1 |
| "CONST", // TOS ==> TOS-1, then ReadOnly |
| "DIM", // DIM |
| "REDIM", // REDIM |
| "REDIMP", // REDIM PRESERVE |
| "ERASE", // delete TOS |
| // Branch |
| "STOP", // End of program |
| "INITFOR", // FOR-Variable init |
| "NEXT", // FOR-Variable increment |
| "CASE", // Begin CASE |
| "ENDCASE", // End CASE |
| "STDERR", // Default error handling |
| "NOERROR", // No error handling |
| "LEAVE", // leave UP |
| // I/O |
| "CHANNEL", // TOS = Channelnumber |
| "PRINT", // print TOS |
| "PRINTF", // print TOS in field |
| "WRITE", // write TOS |
| "RENAME", // Rename Tos+1 to Tos |
| "PROMPT", // TOS = Prompt for Input |
| "RESTART", // Define restart point |
| "STDIO", // Switch to I/O channel 0 |
| // Misc |
| "EMPTY", // Empty statement to stack |
| "ERROR", // TOS = error code |
| "LSET", // Save object TOS ==> TOS-1 |
| "RSET", // Save object TOS ==> TOS-1 (TODO: Same as above?) |
| "REDIMP_ERASE", |
| "INITFOREACH", |
| "VBASET", |
| "ERASE_CLEAR", |
| "ARRAYACCESS", |
| "BYVAL" |
| }; |
| |
| static const char* pOp2[] = { |
| "NUMBER", // Load a numeric constant (+ID) |
| "STRING", // Load a string constant (+ID) |
| "CONSTANT", // Immediate Load (+value) |
| "ARGN", // Save named args in argv (+StringID) |
| "PAD", // Pad String to defined length (+length) |
| // Branches |
| "JUMP", // Jump to target (+Target) |
| "JUMP.T", // evaluate TOS, conditional jump (+Target) |
| "JUMP.F", // evaluate TOS, conditional jump (+Target) |
| "ONJUMP", // evaluate TOS, jump into JUMP-table (+MaxVal) |
| "GOSUB", // UP-Call (+Target) |
| "RETURN", // UP-Return (+0 or Target) |
| "TESTFOR", // Test FOR-Variable, increment (+Endlabel) |
| "CASETO", // Tos+1 <= Case <= Tos, 2xremove (+Target) |
| "ERRHDL", // Error-Handler (+Offset) |
| "RESUME", // Resume after errors (+0 or 1 or Label) |
| // I/O |
| "CLOSE", // (+channel/0) |
| "PRCHAR", // (+char) |
| // Objects |
| "SETCLASS", // Test Set + Classname (+StringId) |
| "TESTCLASS", // Check TOS class (+StringId) |
| "LIB", // Set Libname for Declare-Procs (+StringId) |
| // New since Beta 3 (TODO: Which Beta3?) |
| "BASED", // TOS is incremted about BASE, push BASE before |
| "ARGTYP", // Convert last parameter in argv (+Type) |
| "VBASETCLASS", |
| }; |
| |
| static const char* pOp3[] = { |
| // All opcodes with two operands |
| "RTL", // Load from RTL (+StringID+Typ) |
| "FIND", // Load (+StringID+Typ) |
| "ELEM", // Load element (+StringID+Typ) |
| "PARAM", // Parameter (+Offset+Typ) |
| |
| // Branching |
| "CALL", // Call DECLARE method (+StringID+Typ) |
| "CALL.C", // Call Cdecl-DECLARE method (+StringID+Typ) |
| "CASEIS", // Case-Test (+Test-Opcode+False-Target) |
| "STMNT", // Start of a statement (+Line+Col) |
| |
| // I/O |
| "OPEN", // (+SvStreamFlags+Flags) |
| |
| // Objects and variables |
| "LOCAL", // Local variables (+StringID+Typ) |
| "PUBLIC", // Modul global var (+StringID+Typ) |
| "GLOBAL", // Global var (+StringID+Typ) |
| "CREATE", // Create object (+StringId+StringId) |
| "STATIC", // Create static object (+StringId+StringId) |
| "TCREATE", // Create User defined Object (+StringId+StringId) |
| "DCREATE", // Create User defined Object-Array kreieren (+StringId+StringId) |
| "GLOBAL_P", // Define persistent global var (existing after basic restart) |
| // P=PERSIST (+StringID+Typ) |
| "FIND_G", // Searches for global var with special handling due to _GLOBAL_P |
| "DCREATE_REDIMP", // Change dimensions of a user defined Object-Array (+StringId+StringId) |
| "FIND_CM", // Search inside a class module (CM) to enable global search in time |
| "PUBLIC_P", // Module global Variable (persisted between calls)(+StringID+Typ) |
| "FIND_STATIC", // local static var lookup (+StringID+Typ) |
| }; |
| |
| static const char** pOps[3] = { pOp1, pOp2, pOp3 }; |
| |
| typedef void( SbiDisas::*Func )( String& ); // Processing routines |
| |
| static const Func pOperand2[] = { |
| &SbiDisas::StrOp, // Load a numeric constant (+ID) |
| &SbiDisas::StrOp, // Load a string constant (+ID) |
| &SbiDisas::ImmOp, // Immediate Load (+Wert) |
| &SbiDisas::StrOp, // Save a named argument (+ID) |
| &SbiDisas::ImmOp, // Strip String to fixed size (+length) |
| |
| // Branches |
| &SbiDisas::LblOp, // Jump (+Target) |
| &SbiDisas::LblOp, // eval TOS, conditional jump (+Target) |
| &SbiDisas::LblOp, // eval TOS, conditional jump (+Target) |
| &SbiDisas::OnOp, // eval TOS, jump in JUMP table (+MaxVal) |
| &SbiDisas::LblOp, // UP call (+Target) |
| &SbiDisas::ReturnOp, // UP Return (+0 or Target) |
| &SbiDisas::LblOp, // test FOR-Variable, increment (+Endlabel) |
| &SbiDisas::LblOp, // Tos+1 <= Case <= Tos), 2xremove (+Target) |
| &SbiDisas::LblOp, // Error handler (+Offset) |
| &SbiDisas::ResumeOp, // Resume after errors (+0 or 1 or Label) |
| |
| // I/O |
| &SbiDisas::CloseOp, // (+channel/0) |
| &SbiDisas::CharOp, // (+char) |
| |
| // Objects |
| &SbiDisas::StrOp, // Test classname (+StringId) |
| &SbiDisas::StrOp, // TESTCLASS, Check TOS class (+StringId) |
| &SbiDisas::StrOp, // Set libname for declare procs (+StringId) |
| &SbiDisas::ImmOp, // TOS is incremented about BASE erhoeht, BASE pushed before |
| &SbiDisas::TypeOp, // Convert last parameter to/in(?) argv (+Typ) |
| &SbiDisas::StrOp, // VBASETCLASS (+StringId) |
| }; |
| |
| static const Func pOperand3[] = { |
| // All opcodes with two operands |
| &SbiDisas::VarOp, // Load from RTL (+StringID+Typ) |
| &SbiDisas::VarOp, // Load (+StringID+Typ) |
| &SbiDisas::VarOp, // Load Element (+StringID+Typ) |
| &SbiDisas::OffOp, // Parameter (+Offset+Typ) |
| |
| // Branch |
| &SbiDisas::VarOp, // Call DECLARE-Method (+StringID+Typ) |
| &SbiDisas::VarOp, // Call CDecl-DECLARE-Methode (+StringID+Typ) |
| &SbiDisas::CaseOp, // Case-Test (+Test-Opcode+False-Target) |
| &SbiDisas::StmntOp, // Statement (+Row+Column) |
| |
| // I/O |
| &SbiDisas::StrmOp, // (+SvStreamFlags+Flags) |
| |
| // Objects |
| &SbiDisas::VarDefOp, // Define local var (+StringID+Typ) |
| &SbiDisas::VarDefOp, // Define Module global var (+StringID+Typ) |
| &SbiDisas::VarDefOp, // Define global var (+StringID+Typ) |
| &SbiDisas::Str2Op, // Create object (+StringId+StringId) |
| &SbiDisas::VarDefOp, // Define static object (+StringID+Typ) |
| &SbiDisas::Str2Op, // Create User defined Object (+StringId+StringId) |
| &SbiDisas::Str2Op, // Create User defined Object-Array (+StringId+StringId) |
| &SbiDisas::VarDefOp, // Define persistent global var P=PERSIST (+StringID+Typ) |
| &SbiDisas::VarOp, // Searches for global var with special handling due to _GLOBAL_P |
| &SbiDisas::Str2Op, // Redimensionate User defined Object-Array (+StringId+StringId) |
| &SbiDisas::VarOp, // FIND_CM |
| &SbiDisas::VarDefOp, // PUBLIC_P |
| &SbiDisas::VarOp, // FIND_STATIC |
| }; |
| |
| // TODO: Why as method? Isn't a simple define sufficient? |
| static const char* _crlf() |
| { |
| #if defined (UNX) || defined( PM2 ) |
| return "\n"; |
| #else |
| return "\r\n"; |
| #endif |
| } |
| |
| // This method exists because we want to load the file as own segment |
| sal_Bool SbModule::Disassemble( String& rText ) |
| { |
| rText.Erase(); |
| if( pImage ) |
| { |
| SbiDisas aDisas( this, pImage ); |
| aDisas.Disas( rText ); |
| } |
| return sal_Bool( rText.Len() != 0 ); |
| } |
| |
| SbiDisas::SbiDisas( SbModule* p, const SbiImage* q ) : rImg( *q ), pMod( p ) |
| { |
| memset( cLabels, 0, 8192 ); |
| nLine = 0; |
| nOff = 0; |
| nPC = 0; |
| nOp1 = nOp2 = nParts = 0; |
| eOp = _NOP; |
| // Set Label-Bits |
| nOff = 0; |
| while( Fetch() ) |
| { |
| switch( eOp ) |
| { |
| case _RESUME: if( nOp1 <= 1 ) break; |
| case _RETURN: if( !nOp1 ) break; |
| case _JUMP: |
| case _JUMPT: |
| case _JUMPF: |
| case _GOSUB: |
| case _TESTFOR: |
| case _CASEIS: |
| case _CASETO: |
| case _ERRHDL: |
| cLabels[ (nOp1 & 0xffff) >> 3 ] |= ( 1 << ( nOp1 & 7 ) ); |
| break; |
| default: break; |
| } |
| } |
| nOff = 0; |
| // Add the publics |
| for( sal_uInt16 i = 0; i < pMod->GetMethods()->Count(); i++ ) |
| { |
| SbMethod* pMeth = PTR_CAST(SbMethod,pMod->GetMethods()->Get( i )); |
| if( pMeth ) |
| { |
| sal_uInt16 nPos = (sal_uInt16) (pMeth->GetId()); |
| cLabels[ nPos >> 3 ] |= ( 1 << ( nPos & 7 ) ); |
| } |
| } |
| } |
| |
| // Read current opcode |
| sal_Bool SbiDisas::Fetch() |
| { |
| nPC = nOff; |
| if( nOff >= rImg.GetCodeSize() ) |
| return sal_False; |
| const unsigned char* p = (const unsigned char*)( rImg.GetCode() + nOff ); |
| eOp = (SbiOpcode) ( *p++ & 0xFF ); |
| if( eOp <= SbOP0_END ) |
| { |
| nOp1 = nOp2 = 0; |
| nParts = 1; |
| nOff++; |
| return sal_True; |
| } |
| else if( eOp <= SbOP1_END ) |
| { |
| nOff += 5; |
| if( nOff > rImg.GetCodeSize() ) |
| return sal_False; |
| nOp1 = *p++; nOp1 |= *p++ << 8; nOp1 |= *p++ << 16; nOp1 |= *p++ << 24; |
| nParts = 2; |
| return sal_True; |
| } |
| else if( eOp <= SbOP2_END ) |
| { |
| nOff += 9; |
| if( nOff > rImg.GetCodeSize() ) |
| return sal_False; |
| nOp1 = *p++; nOp1 |= *p++ << 8; nOp1 |= *p++ << 16; nOp1 |= *p++ << 24; |
| nOp2 = *p++; nOp2 |= *p++ << 8; nOp2 |= *p++ << 16; nOp2 |= *p++ << 24; |
| nParts = 3; |
| return sal_True; |
| } |
| else |
| return sal_False; |
| } |
| |
| void SbiDisas::Disas( SvStream& r ) |
| { |
| String aText; |
| nOff = 0; |
| while( DisasLine( aText ) ) |
| { |
| ByteString aByteText( aText, gsl_getSystemTextEncoding() ); |
| r.WriteLine( aByteText ); |
| } |
| } |
| |
| void SbiDisas::Disas( String& r ) |
| { |
| r.Erase(); |
| String aText; |
| nOff = 0; |
| while( DisasLine( aText ) ) |
| { |
| r += aText; |
| r.AppendAscii( _crlf() ); |
| } |
| aText.ConvertLineEnd(); |
| } |
| |
| sal_Bool SbiDisas::DisasLine( String& rText ) |
| { |
| char cBuf[ 100 ]; |
| const char* pMask[] = { |
| "%08" SAL_PRIXUINT32 " ", |
| "%08" SAL_PRIXUINT32 " %02X ", |
| "%08" SAL_PRIXUINT32 " %02X %08X ", |
| "%08" SAL_PRIXUINT32 " %02X %08X %08X " }; |
| rText.Erase(); |
| if( !Fetch() ) |
| return sal_False; |
| |
| #ifdef DBG_TRACE_BASIC |
| String aTraceStr_STMNT; |
| #endif |
| |
| // New line? |
| if( eOp == _STMNT && nOp1 != nLine ) |
| { |
| // Find line |
| String aSource = rImg.aOUSource; |
| nLine = nOp1; |
| sal_uInt16 n = 0; |
| sal_uInt16 l = (sal_uInt16)nLine; |
| while( --l ) { |
| n = aSource.SearchAscii( "\n", n ); |
| if( n == STRING_NOTFOUND ) break; |
| else n++; |
| } |
| // Show position |
| if( n != STRING_NOTFOUND ) |
| { |
| sal_uInt16 n2 = aSource.SearchAscii( "\n", n ); |
| if( n2 == STRING_NOTFOUND ) n2 = aSource.Len() - n; |
| String s( aSource.Copy( n, n2 - n + 1 ) ); |
| sal_Bool bDone; |
| do { |
| bDone = sal_True; |
| n = s.Search( '\r' ); |
| if( n != STRING_NOTFOUND ) bDone = sal_False, s.Erase( n, 1 ); |
| n = s.Search( '\n' ); |
| if( n != STRING_NOTFOUND ) bDone = sal_False, s.Erase( n, 1 ); |
| } while( !bDone ); |
| // snprintf( cBuf, sizeof(cBuf), pMask[ 0 ], nPC ); |
| // rText += cBuf; |
| rText.AppendAscii( "; " ); |
| rText += s; |
| rText.AppendAscii( _crlf() ); |
| |
| #ifdef DBG_TRACE_BASIC |
| aTraceStr_STMNT = s; |
| #endif |
| } |
| } |
| |
| // Label? |
| const char* p = ""; |
| if( cLabels[ nPC >> 3 ] & ( 1 << ( nPC & 7 ) ) ) |
| { |
| // Public? |
| ByteString aByteMethName; |
| for( sal_uInt16 i = 0; i < pMod->GetMethods()->Count(); i++ ) |
| { |
| SbMethod* pMeth = PTR_CAST(SbMethod,pMod->GetMethods()->Get( i )); |
| if( pMeth ) |
| { |
| aByteMethName = ByteString( pMeth->GetName(), gsl_getSystemTextEncoding() ); |
| if( pMeth->GetId() == nPC ) |
| { |
| p = aByteMethName.GetBuffer(); |
| break; |
| } |
| if( pMeth->GetId() >= nPC ) |
| break; |
| } |
| } |
| snprintf( cBuf, sizeof(cBuf), pMask[ 0 ], nPC ); |
| rText.AppendAscii( cBuf ); |
| if( p && *p ) |
| { |
| rText.AppendAscii( p ); |
| } |
| else |
| { |
| // fix warning (now error) for "Lbl%04lX" format |
| snprintf( cBuf, sizeof(cBuf), "Lbl%08" SAL_PRIXUINT32, nPC ); |
| rText.AppendAscii( cBuf ); |
| } |
| rText += ':'; |
| rText.AppendAscii( _crlf() ); |
| } |
| snprintf( cBuf, sizeof(cBuf), pMask[ nParts ], nPC, (sal_uInt16) eOp, nOp1, nOp2 ); |
| |
| String aPCodeStr; |
| aPCodeStr.AppendAscii( cBuf ); |
| int n = eOp; |
| if( eOp >= SbOP2_START ) |
| n -= SbOP2_START; |
| else if( eOp >= SbOP1_START ) |
| n -= SbOP1_START; |
| aPCodeStr += '\t'; |
| aPCodeStr.AppendAscii( pOps[ nParts-1 ][ n ] ); |
| aPCodeStr += '\t'; |
| switch( nParts ) |
| { |
| case 2: (this->*( pOperand2[ n ] ) )( aPCodeStr ); break; |
| case 3: (this->*( pOperand3[ n ] ) )( aPCodeStr ); break; |
| } |
| |
| rText += aPCodeStr; |
| |
| #ifdef DBG_TRACE_BASIC |
| dbg_RegisterTraceTextForPC( pMod, nPC, aTraceStr_STMNT, aPCodeStr ); |
| #endif |
| |
| return sal_True; |
| } |
| |
| // Read from StringPool |
| void SbiDisas::StrOp( String& rText ) |
| { |
| String aStr = rImg.GetString( (sal_uInt16)nOp1 ); |
| ByteString aByteString( aStr, RTL_TEXTENCODING_ASCII_US ); |
| const char* p = aByteString.GetBuffer(); |
| if( p ) |
| { |
| rText += '"'; |
| rText.AppendAscii( p ); |
| rText += '"'; |
| } |
| else |
| { |
| rText.AppendAscii( "?String? " ); |
| rText += (sal_uInt16)nOp1; |
| } |
| } |
| |
| void SbiDisas::Str2Op( String& rText ) |
| { |
| StrOp( rText ); |
| rText += ','; |
| String s; |
| nOp1 = nOp2; |
| StrOp( s ); |
| rText += s; |
| } |
| |
| // Immediate Operand |
| void SbiDisas::ImmOp( String& rText ) |
| { |
| rText += String::CreateFromInt32(nOp1); |
| } |
| |
| // OnGoto Operand |
| void SbiDisas::OnOp( String& rText ) |
| { |
| rText += String::CreateFromInt32(nOp1 & 0x7FFF); |
| if( nOp1 & 0x800 ) |
| rText.AppendAscii( "\t; Gosub" ); |
| } |
| |
| // Label |
| void SbiDisas::LblOp( String& rText ) |
| { |
| char cBuf[ 10 ]; |
| snprintf( cBuf, sizeof(cBuf), "Lbl%04" SAL_PRIXUINT32, nOp1 ); |
| rText.AppendAscii( cBuf ); |
| } |
| |
| // 0 or Label |
| void SbiDisas::ReturnOp( String& rText ) |
| { |
| if( nOp1 ) |
| LblOp( rText ); |
| } |
| |
| // 0, 1 or Label |
| void SbiDisas::ResumeOp( String& rText ) |
| { |
| switch( nOp1 ) |
| { |
| case 1: rText.AppendAscii( "NEXT" ); break; |
| case 2: LblOp( rText ); |
| } |
| } |
| |
| // print Prompt |
| // sal_False/TRUE |
| void SbiDisas::PromptOp( String& rText ) |
| { |
| if( nOp1 ) |
| rText.AppendAscii( "\"? \"" ); |
| } |
| |
| // 0 or 1 |
| void SbiDisas::CloseOp( String& rText ) |
| { |
| rText.AppendAscii( nOp1 ? "Channel" : "All" ); |
| } |
| |
| // Print character |
| void SbiDisas::CharOp( String& rText ) |
| { |
| const char* p = NULL; |
| switch( nOp1 ) |
| { |
| case 7: p = "'\\a'"; break; |
| case 9: p = "'\\t'"; break; |
| case 10: p = "'\\n'"; break; |
| case 12: p = "'\\f'"; break; |
| case 13: p = "'\\r'"; break; |
| } |
| if( p ) rText.AppendAscii( p ); |
| else if( nOp1 >= ' ' ) |
| rText += '\'', |
| rText += (char) nOp1, |
| rText += '\''; |
| else |
| rText.AppendAscii( "char " ), |
| rText += (sal_uInt16)nOp1; |
| } |
| |
| // Print var: String-ID and type |
| void SbiDisas::VarOp( String& rText ) |
| { |
| rText += rImg.GetString( (sal_uInt16)(nOp1 & 0x7FFF) ); |
| rText.AppendAscii( "\t; " ); |
| // The type |
| sal_uInt32 n = nOp1; |
| nOp1 = nOp2; |
| TypeOp( rText ); |
| if( n & 0x8000 ) |
| rText.AppendAscii( ", Args" ); |
| } |
| |
| // Define variable: String-ID and type |
| void SbiDisas::VarDefOp( String& rText ) |
| { |
| rText += rImg.GetString( (sal_uInt16)(nOp1 & 0x7FFF) ); |
| rText.AppendAscii( "\t; " ); |
| // The Typ |
| nOp1 = nOp2; |
| TypeOp( rText ); |
| } |
| |
| // Print variable: Offset and Typ |
| void SbiDisas::OffOp( String& rText ) |
| { |
| rText += String::CreateFromInt32( nOp1 & 0x7FFF ); |
| rText.AppendAscii( "\t; " ); |
| // The type |
| sal_uInt32 n = nOp1; |
| nOp1 = nOp2; |
| TypeOp( rText ); |
| if( n & 0x8000 ) |
| rText.AppendAscii( ", Args" ); |
| } |
| |
| // Data type |
| #ifdef HP9000 // TODO: remove this! |
| static char* SbiDisas_TypeOp_pTypes[13] = { |
| "Empty","Null","Integer","Long","Single","Double", |
| "Currency","Date","String","Object","Error","Boolean", |
| "Variant" }; |
| #define pTypes SbiDisas_TypeOp_pTypes |
| #endif |
| void SbiDisas::TypeOp( String& rText ) |
| { |
| // AB 19.1.96: Typ kann Flag für BYVAL enthalten (StepARGTYP) |
| if( nOp1 & 0x8000 ) |
| { |
| nOp1 &= 0x7FFF; // Flag wegfiltern |
| rText.AppendAscii( "BYVAL " ); |
| } |
| if( nOp1 < 13 ) |
| { |
| #ifndef HP9000 |
| static char pTypes[][13] = { |
| "Empty","Null","Integer","Long","Single","Double", |
| "Currency","Date","String","Object","Error","Boolean", |
| "Variant" }; |
| #endif |
| rText.AppendAscii( pTypes[ nOp1 ] ); |
| } |
| else |
| { |
| rText.AppendAscii( "type " ); |
| rText += (sal_uInt16)nOp1; |
| } |
| } |
| #ifdef HP9000 |
| #undef pTypes |
| #endif |
| |
| // sal_True-Label, condition Opcode |
| void SbiDisas::CaseOp( String& rText ) |
| { |
| LblOp( rText ); |
| rText += ','; |
| rText.AppendAscii( pOp1[ nOp2 - SbxEQ + _EQ ] ); |
| } |
| |
| // Row, column |
| void SbiDisas::StmntOp( String& rText ) |
| { |
| rText += String::CreateFromInt32( nOp1 ); |
| rText += ','; |
| sal_uInt32 nCol = nOp2 & 0xFF; |
| sal_uInt32 nFor = nOp2 / 0x100; |
| rText += String::CreateFromInt32( nCol ); |
| rText.AppendAscii( " (For-Level: " ); |
| rText += String::CreateFromInt32( nFor ); |
| rText += ')'; |
| } |
| |
| // open mode, flags |
| void SbiDisas::StrmOp( String& rText ) |
| { |
| char cBuf[ 10 ]; |
| snprintf( cBuf, sizeof(cBuf), "%04" SAL_PRIXUINT32, nOp1 ); |
| rText.AppendAscii( cBuf ); |
| if( nOp2 & SBSTRM_INPUT ) |
| rText.AppendAscii( ", Input" ); |
| if( nOp2 & SBSTRM_OUTPUT ) |
| rText.AppendAscii( ", Output" ); |
| if( nOp2 & SBSTRM_APPEND ) |
| rText.AppendAscii( ", Append" ); |
| if( nOp2 & SBSTRM_RANDOM ) |
| rText.AppendAscii( ", Random" ); |
| if( nOp2 & SBSTRM_BINARY ) |
| rText.AppendAscii( ", Binary" ); |
| } |
| |
| |