1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <stardiv/uno/repos/implementationregistration.hxx>
23 #include <stardiv/uno/script/script.hxx>
24 #include <stardiv/uno/beans/exactname.hxx>
26 #include <rtl/ustring.hxx>
27 #include <osl/diagnose.h>
28 #include <usr/services.hxx>
29 #include <vcl/svapp.hxx>
30 #include <usr/ustring.hxx>
31 #include <usr/weak.hxx>
32 #include <osl/conditn.hxx>
36 using ::rtl::StringToOUString
;
39 #define PCHAR_TO_USTRING(x) StringToOUString(String(x),CHARSET_SYSTEM)
43 class NullEngineListenerRef
: public XEngineListenerRef
45 virtual void interrupt(const InterruptEngineEvent
& Evt
) THROWS( (UsrSystemException
) ) {}
46 virtual void running(const EventObject
& Evt
) THROWS( (UsrSystemException
) ) {}
47 virtual void finished(const FinishEngineEvent
& Evt
) THROWS( (UsrSystemException
) ) {}
50 #define USTRING_TO_PCHAR(x) OUStringToString(x , CHARSET_DONTKNOW ).GetCharStr()
53 public XEngineListener
,
62 m_bIsTerminating
= FALSE
;
67 CmdDebugger( XDebuggingRef
*p
, XEngineRef
*pEngine
, XInvokationRef
*pInvokation
)
69 attach( p
, pEngine
, pInvokation
);
74 if( m_pDebuggingRef
) {
79 BOOL
queryInterface( Uik aUik
, XInterfaceRef
& rOut
);
80 void acquire() { OWeakObject::acquire(); }
81 void release() { OWeakObject::release(); }
82 void* getImplementation(Reflection
*p
) { return OWeakObject::getImplementation(p
); }
85 void attach( XDebuggingRef
*p
, XEngineRef
*pEngine
, XInvokationRef
*pInvokation
)
88 m_pEngineRef
= pEngine
;
89 m_pInvokationRef
= pInvokation
;
91 m_bIsTerminating
= FALSE
;
97 virtual void disposing( const EventObject
&o
)
99 if( m_pDebuggingRef
) {
103 virtual void interrupt(const InterruptEngineEvent
& Evt
) THROWS( (UsrSystemException
) )
105 if( m_pDebuggingRef
&& ! m_bIsTerminating
) {
106 (*m_pDebuggingRef
)->stop();
107 fprintf( stderr
, "%s\n" , USTRING_TO_PCHAR(Evt
.ErrorMessage
) );
108 fprintf( stderr
, "%s.%s (%d)\n", USTRING_TO_PCHAR(Evt
.SourceCode
),
109 USTRING_TO_PCHAR(Evt
.Name
),
111 m_aDebugCondition
.set();
116 virtual void running(const EventObject
& Evt
) THROWS( (UsrSystemException
) )
118 if( m_pDebuggingRef
&& ! m_bIsTerminating
) {
119 (*m_pDebuggingRef
)->stop();
121 m_aDebugCondition
.set();
123 fprintf( stderr
, "%s\n" , "Script starts\n" );
127 virtual void finished(const FinishEngineEvent
& Evt
) THROWS( (UsrSystemException
) )
129 if( m_pDebuggingRef
&& ! m_bIsTerminating
) {
130 m_aDebugCondition
.set();
131 m_bIsRunning
= FALSE
;
132 fprintf( stderr
, "%s\n", USTRING_TO_PCHAR( Evt
.ErrorMessage
) );
136 void dumpIntrospectionToStream( const XIntrospectionAccessRef
&, FILE *f
);
137 void dumpVarToStream( const char *pcName
, const UsrAny
&any
, FILE *f
);
143 osl::Condition m_aDebugCondition
;
144 XDebuggingRef
*m_pDebuggingRef
;
145 XEngineRef
*m_pEngineRef
;
146 XInvokationRef
*m_pInvokationRef
;
148 int m_bIsTerminating
; // The listeners ignore everything when set
153 void CmdDebugger::cmdLine()
156 fprintf( stderr
, "entering debugger\n" );
159 m_aDebugCondition
.wait();
161 fprintf( stderr
, "(debug %d) : " , m_bIsRunning
);
163 fgets( pcLine
, 79 , stdin
);
165 if( strlen( pcLine
) ) pcLine
[strlen(pcLine
)-1] =0;
166 String
sLine( pcLine
);
168 if( ! strcmp( pcLine
, "g" ) ) {
170 m_aDebugCondition
.reset();
171 (*m_pDebuggingRef
)->doContinue();
173 else fprintf( stderr
,"no script running !\n" );
175 else if( ! strcmp( pcLine
, "s" ) ) {
177 m_aDebugCondition
.reset();
178 (*m_pDebuggingRef
)->stepOver();
180 else fprintf(stderr
, "no script running !\n" );
182 else if( ! strcmp( pcLine
, "so" ) ) {
184 m_aDebugCondition
.reset();
185 (*m_pDebuggingRef
)->stepOut();
187 else fprintf(stderr
, "no script running !\n" );
189 else if( ! strcmp( pcLine
, "si" ) ) {
191 m_aDebugCondition
.reset();
192 (*m_pDebuggingRef
)->stepIn();
194 else fprintf(stderr
, "no script running !\n" );
196 else if( ! strncmp( pcLine
, "sbp" , 3 ) ){
198 (*m_pDebuggingRef
)->setBreakPoint( UString( L
"<string>" ),
199 atoi(&pcLine
[3]) , TRUE
);
202 else if( ! strncmp( pcLine
, "rbp" , 3 ) ){
204 (*m_pDebuggingRef
)->setBreakPoint( UString( L
"<string>" ),
205 atoi(&pcLine
[3]) , FALSE
);
208 else if( ! strncmp( pcLine
, "dv " , 3 ) ) {
211 if( sLine
.GetQuotedTokenCount( String("''"),' ' ) == 3 ) {
212 nCallstack
= atoi( sLine
.GetQuotedToken( 3 , String("''"), ' ' ).GetCharStr() );
215 UString str
= (*m_pDebuggingRef
)->dumpVariable(
216 PCHAR_TO_USTRING( &pcLine
[3]),nCallstack
);
217 fprintf( stderr
, "%s\n" , USTRING_TO_PCHAR( str
) );
220 else if( ! strncmp( pcLine
, "sv " , 3 ) ) {
222 if( sLine
.GetQuotedTokenCount( String("''"),' ' ) == 3 ) {
223 nCallstack
= atoi( sLine
.GetQuotedToken( 3 , String("''"), ' ' ).GetCharStr() );
225 (*m_pDebuggingRef
)->setVariable(
226 StringToOUString( sLine
.GetQuotedToken( 1 , String("''"), ' ' ), CHARSET_SYSTEM
),
227 StringToOUString( sLine
.GetQuotedToken( 2 , String("''"), ' ' ), CHARSET_SYSTEM
),
231 else if( ! strncmp( pcLine
, "ci" ,2 ) ) {
234 ContextInformation ci
= (*m_pDebuggingRef
)->getContextInformation(atoi(&pcLine
[2]));
237 fprintf( stderr
, "File %s (%d)\n", USTRING_TO_PCHAR(ci
.Name
),
239 fprintf( stderr
, "Available variables : \n" );
240 aUString
= ci
.LocalVariableNames
.getArray();
241 iMax
= ci
.LocalVariableNames
.getLen();
243 for( i
= 0 ; i
< iMax
; i
++ ) {
244 fprintf( stderr
, " %s\n" , USTRING_TO_PCHAR( aUString
[i
]) );
248 else if ( !strcmp( pcLine
, "d" ) ) {
251 Sequence
<UString
> seq
= (*m_pDebuggingRef
)->getStackTrace();
253 aUString
= seq
.getArray();
254 int iMax
= seq
.getLen();
255 for( int i
= 0; i
< iMax
; i
++ ) {
256 fprintf( stderr
, "%s\n" , USTRING_TO_PCHAR( aUString
[i
] ) );
260 else if( !strcmp( pcLine
, "c" ) ) {
262 (*m_pEngineRef
)->cancel();
263 m_aDebugCondition
.reset();
265 else fprintf( stderr
,"no script running !\n" );
267 else if( !strcmp( pcLine
, "q" ) ) {
269 m_aDebugCondition
.reset();
270 (*m_pEngineRef
)->cancel();
273 m_bIsTerminating
= TRUE
;
274 fprintf(stderr
, "Debugger terminates\n" );
278 else if( ! strcmp( pcLine
, "id" ) ) {
280 XIntrospectionAccessRef ref
= (*m_pInvokationRef
)->getIntrospection();
282 dumpIntrospectionToStream( ref
, stderr
);
286 else if( ! strncmp( pcLine
, "idv" , 3) ) {
288 UsrAny any
= (*m_pInvokationRef
)->getValue( PCHAR_TO_USTRING( &(pcLine
[4]) ) );
289 dumpVarToStream( &(pcLine
[4]) , any
, stderr
);
291 catch(UnknownPropertyException
& e
) {
292 fprintf( stderr
, "UnknownPropertyException\n" );
294 catch(IllegalArgumentException
& e
) {
295 fprintf( stderr
, "IllegalArgumentException\n" );
298 else if( !strcmp( pcLine
, "t" ) ) {
300 else if( !strcmp( pcLine
, "h" ) ) {
301 fprintf( stderr
, "\nvalid commands :\n"
306 "Set BreakPoint : sbp Line [ModuleName]\n"
307 "Remove BreakPoint : rbp [Line] [ModuleName]\n"
308 "via XDebugging Interface :\n"
309 " dump Variable : dv varname [CallStack]\n"
310 " set Variable : sv varname value [CallStack]\n"
311 "globals via XInvokation Interface :\n"
312 " dump Global vars : id\n"
313 " dump Variable : idv varname\n"
314 " set Variable : isv varname value\n"
315 "ContextInformation : ci\n"
316 "Dump callstack : d\n"
317 "Cancel : c (stops actual script)\n"
318 "Quit : q (exits debugger)\n"
321 else if( ! strlen( pcLine
) ) {
324 fprintf( stderr
, "unknown command %s\n" , pcLine
);
329 void CmdDebugger::dumpIntrospectionToStream( const XIntrospectionAccessRef
&ref
, FILE *f
)
332 fprintf( stderr
, "Callable Attributes (Methods) :\n" );
333 Sequence
<XIdlMethodRef
> seq
= ref
->getMethods( 0 );
335 XIdlMethodRef
*aRef
= seq
.getArray();
336 for( i
= 0; i
< iMax
; i
++ ) {
337 fprintf( f
, " %s\n" , USTRING_TO_PCHAR( aRef
[i
]->getName( ) ) );
340 fprintf( stderr
, "Other attributes\n" );
341 Sequence
<Property
> seqProp
= ref
->getProperties( 0 );
342 iMax
= seqProp
.getLen();
343 Property
*aProp
= seqProp
.getArray();
344 for( i
= 0; i
< iMax
; i
++ ) {
345 fprintf( f
, " %s %s\n" , USTRING_TO_PCHAR( aProp
[i
].Type
->getName() ),
346 USTRING_TO_PCHAR( aProp
[i
].Name
) );
351 void CmdDebugger::dumpVarToStream( const char *pc
, const UsrAny
&aValue
, FILE *f
)
353 TypeClass type
= aValue
.getReflection()->getTypeClass();
355 if( TypeClass_INT
== type
) {
356 fprintf( f
, "INT32 %s : %d\n" , pc
, aValue
.getINT32() );
358 else if( TypeClass_ENUM
== type
) {
359 fprintf( f
, "ENUM %s : %d\n", pc
, aValue
.getEnumAsINT32() );
361 else if( TypeClass_STRING
== type
) {
362 fprintf( f
, "STRING %s : %s\n" , pc
, USTRING_TO_PCHAR( aValue
.getString()) );
364 else if( TypeClass_BOOLEAN
== type
) {
365 fprintf( f
, "BOOL %s : %d\n", pc
, aValue
.getBOOL() );
367 else if( TypeClass_CHAR
== type
) {
368 fprintf( f
, "char %s : %d\n", pc
, ( INT32
) aValue
.getChar() );
370 else if( TypeClass_SHORT
== type
) {
371 fprintf( f
, "INT16 %s : %d\n", pc
, (INT32
) aValue
.getINT16());
373 else if( TypeClass_LONG
== type
) {
374 fprintf( f
, "LONG %s : %d\n", pc
, (INT32
) aValue
.getINT32());
376 else if( TypeClass_UNSIGNED_SHORT
== type
) {
377 fprintf( f
, "UINT16 %s : %d\n", pc
, (INT32
) aValue
.getUINT16() );
379 else if( TypeClass_UNSIGNED_BYTE
== type
) {
380 fprintf( f
, "Byte %s : %d\n", pc
, (INT32
) aValue
.getBYTE() );
382 else if( TypeClass_UNSIGNED_INT
== type
) {
383 fprintf( f
, "UINT32 %s : %d\n", pc
, aValue
.getUINT32() );
385 else if( TypeClass_FLOAT
== type
) {
386 fprintf( f
, "float %s : %f\n" , pc
, aValue
.getFloat() );
388 else if( TypeClass_DOUBLE
== type
) {
389 fprintf( f
, "double %s : %f\n" , pc
, aValue
.getDouble() );
391 else if( TypeClass_VOID
== type
) {
392 fprintf( f
, "void %s :\n" , pc
);
394 else if( TypeClass_INTERFACE
== type
) {
395 // Check, what has been put in
396 if( aValue
.getReflection() == XPropertySet_getReflection() ) {
398 XPropertySetRef
*pRef
= ( XPropertySetRef
* ) aValue
.get();
399 XPropertySetInfoRef refInfo
= (*pRef
)->getPropertySetInfo();
400 Sequence
< Property
> seq
= refInfo
->getProperties();
401 int i
,iMax
= seq
.getLen();
404 pArray
= seq
.getArray();
405 fprintf( stderr
, "Property List :\n" );
406 for( i
= 0; i
< iMax
; i
++ ) {
407 fprintf( f
, "%s\t %s\n" , USTRING_TO_PCHAR(pArray
[i
].Type
->getName()),
408 USTRING_TO_PCHAR( pArray
[i
].Name
) );
411 else if( aValue
.getReflection() == XInvokation_getReflection() ) {
412 XInvokationRef
*pRef
= ( XInvokationRef
* ) aValue
.get();
413 XIntrospectionAccessRef refIntro
= (*pRef
)->getIntrospection();
415 dumpIntrospectionToStream( refIntro
, stderr
);
418 else if( TypeClass_SEQUENCE
== type
) {
419 fprintf( f
, "%s Sequence \n" , pc
);
422 SequenceReflection
*pSeqRefl
= ( SequenceReflection
* ) aValue
.getReflection();
424 int i
,iMax
= pSeqRefl
->getLen( aValue
);
426 for( i
= 0 ; i
< iMax
; i
++ ) {
427 dumpVarToStream( s
.GetCharStr() , pSeqRefl
->get( aValue
, i
) , stderr
);
431 fprintf( f
, "%s : unknown %d\n" , pc
, type
);
436 void CmdDebugger::detach()
438 OSL_ASSERT( m_pDebuggingRef
);
440 m_bIsRunning
= FALSE
;
443 m_pInvokationRef
= 0;
446 // Methoden von XInterface
447 BOOL
CmdDebugger::queryInterface( Uik aUik
, XInterfaceRef
& rOut
)
449 if( aUik
== XEngineListener::getSmartUik() )
450 rOut
= (XEngineListener
*)this;
452 return OWeakObject::queryInterface( aUik
, rOut
);
464 int SAL_CALL
main (int argc
, char **argv
)
466 XMultiServiceFactoryRef xSMgr
= createRegistryServiceManager();
467 registerUsrServices( xSMgr
);
468 setProcessServiceManager( xSMgr
);
470 XInterfaceRef x
= xSMgr
->createInstance( L
"stardiv.uno.repos.ImplementationRegistration" );
471 XImplementationRegistrationRef
xReg( x
, USR_QUERY
);
472 sal_Char szBuf
[1024];
474 ORealDynamicLoader::computeModuleName( "pythonengine", szBuf
, 1024 );
475 UString
aDllName( StringToOUString( szBuf
, CHARSET_SYSTEM
) );
476 xReg
->registerImplementation( L
"stardiv.loader.SharedLibrary", aDllName
, XSimpleRegistryRef() );
478 ORealDynamicLoader::computeModuleName( "aps", szBuf
, 1024 );
479 aDllName
= UString( StringToOUString( szBuf
, CHARSET_SYSTEM
) );
480 xReg
->registerImplementation( L
"stardiv.loader.SharedLibrary", aDllName
, XSimpleRegistryRef() );
482 XInterfaceRef y
= xSMgr
->createInstance( L
"stardiv.script.Python" );
483 XEngineRef
yEngine( y
, USR_QUERY
);
485 x
= xSMgr
->createInstance( L
"stardiv.script.Python" );
486 XEngineRef
xEngine( x
, USR_QUERY
);
491 Sequence
<UsrAny
> args(3);
492 UsrAny
*pArray
= args
.getArray();
493 pArray
[0].setString( L
"Arg_0" );
494 pArray
[1].setString( L
"Arg_1" );
495 pArray
[2].setString( L
"Arg_2" );
498 Script
= StringToOUString( String( argv
[2] ) , CHARSET_DONTKNOW
);
501 XInvokationRef
xInvokation( x
, USR_QUERY
);
502 XDebuggingRef
xDebug( x
, USR_QUERY
);
504 CmdDebugger
*pDbg
= new CmdDebugger( &xDebug
, &xEngine
, &xInvokation
);
506 XEngineListenerRef
xDebugRef( (XEngineListener
*) pDbg
, USR_QUERY
);
507 xEngine
->addEngineListener( xDebugRef
);
510 if( argc
>1 && ! strcmp( argv
[1] , "1" ) ) {
511 fprintf( stderr
, "one thread only\n" );
512 Script
= UString( L
"print 'Hello World'\n" );
513 xEngine
->runAsync( Script
, XInterfaceRef(), args
, XEngineListenerRef() );
515 else if( argc
>1 && ! strcmp( argv
[1] , "2" ) ) {
517 xEngine
->runAsync( UString( L
"x=1\nprint 1\n") , XInterfaceRef(), args
, XEngineListenerRef() );
518 xEngine
->runAsync( UString( L
"x=x+1\nprint 2\n") , XInterfaceRef(), args
, XEngineListenerRef() );
519 xEngine
->runAsync( UString( L
"x=x+1\nprint 3\n") , XInterfaceRef(), args
, XEngineListenerRef());
520 xEngine
->runAsync( UString( L
"x=x+1\nprint 4\n") , XInterfaceRef(), args
, XEngineListenerRef() );
525 else if( argc
>1 && ! strcmp( argv
[1] , "3" ) ) {
527 fprintf( stderr
, "1st thread in engine y, next 5 threads in engine x\n" );
528 yEngine
->runAsync( UString( L
"print 1\n") , XInterfaceRef(), args
, XEngineListenerRef() );
529 xEngine
->runAsync( UString( L
"print 2\n") , XInterfaceRef(), args
, XEngineListenerRef() );
530 xEngine
->runAsync( UString( L
"print 3\n") , XInterfaceRef(), args
, XEngineListenerRef() );
531 xEngine
->runAsync( UString( L
"print 4\n") , XInterfaceRef(), args
, XEngineListenerRef());
532 xEngine
->runAsync( UString( L
"print 5\n") , XInterfaceRef(), args
, XEngineListenerRef());
533 xEngine
->runAsync( UString( L
"print 6\n") , XInterfaceRef(), args
, XEngineListenerRef());
539 xEngine
->removeEngineListener( xDebugRef
);
541 xReg
->revokeImplementation( aDllName
, XSimpleRegistryRef() );
543 fprintf( stderr
, "main terminates\n" );
547 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */