xref: /trunk/main/basic/source/classes/disas.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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