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