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_extensions.hxx" 30 31 #include <stdio.h> 32 #include <stardiv/uno/repos/implementationregistration.hxx> 33 #include <stardiv/uno/script/script.hxx> 34 #include <stardiv/uno/beans/exactname.hxx> 35 36 #include <rtl/ustring.hxx> 37 #include <vos/dynload.hxx> 38 #include <vos/diagnose.hxx> 39 #include <usr/services.hxx> 40 #include <vcl/svapp.hxx> 41 #include <usr/ustring.hxx> 42 #include <usr/weak.hxx> 43 #include <tools/string.hxx> 44 #include <vos/conditn.hxx> 45 46 using namespace rtl; 47 using namespace vos; 48 using namespace usr; 49 50 #define PCHAR_TO_USTRING(x) StringToOUString(String(x),CHARSET_SYSTEM) 51 52 53 54 class NullEngineListenerRef : public XEngineListenerRef 55 { 56 virtual void interrupt(const InterruptEngineEvent& Evt) THROWS( (UsrSystemException) ) {} 57 virtual void running(const EventObject& Evt) THROWS( (UsrSystemException) ) {} 58 virtual void finished(const FinishEngineEvent& Evt) THROWS( (UsrSystemException) ) {} 59 }; 60 61 #define USTRING_TO_PCHAR(x) OUStringToString(x , CHARSET_DONTKNOW ).GetCharStr() 62 63 class CmdDebugger : 64 public XEngineListener, 65 public OWeakObject 66 { 67 public: 68 69 CmdDebugger() 70 { 71 m_pDebuggingRef = 0; 72 m_pEngineRef = 0; 73 m_bIsTerminating = FALSE; 74 m_bIsRunning = FALSE; 75 } 76 77 78 CmdDebugger( XDebuggingRef *p, XEngineRef *pEngine , XInvokationRef *pInvokation) 79 { 80 attach( p , pEngine , pInvokation ); 81 } 82 83 ~CmdDebugger() 84 { 85 if( m_pDebuggingRef ) { 86 detach(); 87 } 88 } 89 90 BOOL queryInterface( Uik aUik, XInterfaceRef & rOut ); 91 void acquire() { OWeakObject::acquire(); } 92 void release() { OWeakObject::release(); } 93 void* getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); } 94 95 96 void attach( XDebuggingRef *p , XEngineRef *pEngine , XInvokationRef *pInvokation ) 97 { 98 m_pDebuggingRef = p; 99 m_pEngineRef = pEngine; 100 m_pInvokationRef = pInvokation; 101 m_bIsRunning = FALSE; 102 m_bIsTerminating = FALSE; 103 } 104 105 void detach( ); 106 107 108 virtual void disposing( const EventObject &o ) 109 { 110 if( m_pDebuggingRef ) { 111 detach(); 112 } 113 } 114 virtual void interrupt(const InterruptEngineEvent& Evt) THROWS( (UsrSystemException) ) 115 { 116 if( m_pDebuggingRef && ! m_bIsTerminating ) { 117 (*m_pDebuggingRef)->stop(); 118 fprintf( stderr, "%s\n" , USTRING_TO_PCHAR(Evt.ErrorMessage ) ); 119 fprintf( stderr, "%s.%s (%d)\n", USTRING_TO_PCHAR(Evt.SourceCode), 120 USTRING_TO_PCHAR(Evt.Name ), 121 Evt.StartLine ); 122 m_aDebugCondition.set(); 123 m_bIsRunning = TRUE; 124 } 125 } 126 127 virtual void running(const EventObject& Evt) THROWS( (UsrSystemException) ) 128 { 129 if( m_pDebuggingRef && ! m_bIsTerminating ) { 130 (*m_pDebuggingRef)->stop(); 131 132 m_aDebugCondition.set(); 133 m_bIsRunning = TRUE; 134 fprintf( stderr, "%s\n" , "Script starts\n" ); 135 } 136 } 137 138 virtual void finished(const FinishEngineEvent& Evt) THROWS( (UsrSystemException) ) 139 { 140 if( m_pDebuggingRef && ! m_bIsTerminating ) { 141 m_aDebugCondition.set(); 142 m_bIsRunning = FALSE; 143 fprintf( stderr , "%s\n", USTRING_TO_PCHAR( Evt.ErrorMessage ) ); 144 } 145 } 146 147 void dumpIntrospectionToStream( const XIntrospectionAccessRef &, FILE *f ); 148 void dumpVarToStream( const char *pcName, const UsrAny &any, FILE *f ); 149 150 151 void cmdLine(); 152 protected: 153 154 OCondition m_aDebugCondition; 155 XDebuggingRef *m_pDebuggingRef; 156 XEngineRef *m_pEngineRef; 157 XInvokationRef *m_pInvokationRef; 158 int m_bIsRunning; 159 int m_bIsTerminating; // The listeners ignore everything when set 160 }; 161 162 163 164 void CmdDebugger::cmdLine() 165 { 166 char pcLine[80]; 167 fprintf( stderr, "entering debugger\n" ); 168 while( TRUE ) { 169 170 m_aDebugCondition.wait(); 171 172 fprintf( stderr , "(debug %d) : " , m_bIsRunning ); 173 fflush( stderr); 174 fgets( pcLine , 79 , stdin ); 175 176 if( strlen( pcLine) ) pcLine[strlen(pcLine)-1] =0; 177 String sLine( pcLine ); 178 179 if( ! strcmp( pcLine , "g" ) ) { 180 if( m_bIsRunning ) { 181 m_aDebugCondition.reset(); 182 (*m_pDebuggingRef)->doContinue(); 183 } 184 else fprintf( stderr,"no script running !\n" ); 185 } 186 else if( ! strcmp( pcLine , "s" ) ) { 187 if( m_bIsRunning ) { 188 m_aDebugCondition.reset(); 189 (*m_pDebuggingRef)->stepOver(); 190 } 191 else fprintf(stderr, "no script running !\n" ); 192 } 193 else if( ! strcmp( pcLine , "so" ) ) { 194 if( m_bIsRunning ) { 195 m_aDebugCondition.reset(); 196 (*m_pDebuggingRef)->stepOut(); 197 } 198 else fprintf(stderr, "no script running !\n" ); 199 } 200 else if( ! strcmp( pcLine , "si" ) ) { 201 if( m_bIsRunning ) { 202 m_aDebugCondition.reset(); 203 (*m_pDebuggingRef)->stepIn(); 204 } 205 else fprintf(stderr, "no script running !\n" ); 206 } 207 else if( ! strncmp( pcLine , "sbp" , 3 ) ){ 208 if( m_bIsRunning ) { 209 (*m_pDebuggingRef)->setBreakPoint( UString( L"<string>" ), 210 atoi(&pcLine[3]) , TRUE ); 211 } 212 } 213 else if( ! strncmp( pcLine , "rbp" , 3 ) ){ 214 if( m_bIsRunning ) { 215 (*m_pDebuggingRef)->setBreakPoint( UString( L"<string>" ), 216 atoi(&pcLine[3]) , FALSE ); 217 } 218 } 219 else if( ! strncmp( pcLine , "dv " , 3 ) ) { 220 if( m_bIsRunning ) { 221 int nCallstack = 0; 222 if( sLine.GetQuotedTokenCount( String("''"),' ' ) == 3 ) { 223 nCallstack = atoi( sLine.GetQuotedToken( 3 , String("''"), ' ' ).GetCharStr() ); 224 } 225 226 UString str = (*m_pDebuggingRef)->dumpVariable( 227 PCHAR_TO_USTRING( &pcLine[3]),nCallstack); 228 fprintf( stderr, "%s\n" , USTRING_TO_PCHAR( str ) ); 229 } 230 } 231 else if( ! strncmp( pcLine , "sv " , 3 ) ) { 232 int nCallstack = 0; 233 if( sLine.GetQuotedTokenCount( String("''"),' ' ) == 3 ) { 234 nCallstack = atoi( sLine.GetQuotedToken( 3 , String("''"), ' ' ).GetCharStr() ); 235 } 236 (*m_pDebuggingRef)->setVariable( 237 StringToOUString( sLine.GetQuotedToken( 1 , String("''"), ' ' ), CHARSET_SYSTEM ), 238 StringToOUString( sLine.GetQuotedToken( 2 , String("''"), ' ' ), CHARSET_SYSTEM ), 239 nCallstack ); 240 241 } 242 else if( ! strncmp( pcLine , "ci" ,2 ) ) { 243 if( m_bIsRunning ) { 244 UString *aUString ; 245 ContextInformation ci = (*m_pDebuggingRef)->getContextInformation(atoi(&pcLine[2])); 246 int i,iMax; 247 248 fprintf( stderr, "File %s (%d)\n", USTRING_TO_PCHAR(ci.Name), 249 ci.StartLine ); 250 fprintf( stderr, "Available variables : \n" ); 251 aUString = ci.LocalVariableNames.getArray(); 252 iMax = ci.LocalVariableNames.getLen(); 253 254 for( i = 0 ; i < iMax ; i++ ) { 255 fprintf( stderr, " %s\n" , USTRING_TO_PCHAR( aUString[i]) ); 256 } 257 } 258 } 259 else if ( !strcmp( pcLine , "d" ) ) { 260 if( m_bIsRunning ) { 261 UString * aUString ; 262 Sequence<UString> seq = (*m_pDebuggingRef)->getStackTrace(); 263 264 aUString = seq.getArray(); 265 int iMax = seq.getLen(); 266 for( int i = 0; i < iMax ; i++ ) { 267 fprintf( stderr , "%s\n" , USTRING_TO_PCHAR( aUString[i] ) ); 268 } 269 } 270 } 271 else if( !strcmp( pcLine , "c" ) ) { 272 if( m_bIsRunning ) { 273 (*m_pEngineRef)->cancel(); 274 m_aDebugCondition.reset(); 275 } 276 else fprintf( stderr,"no script running !\n" ); 277 } 278 else if( !strcmp( pcLine , "q" ) ) { 279 if( m_bIsRunning ) { 280 m_aDebugCondition.reset(); 281 (*m_pEngineRef)->cancel(); 282 } 283 else { 284 m_bIsTerminating = TRUE; 285 fprintf(stderr, "Debugger terminates\n" ); 286 break; 287 } 288 } 289 else if( ! strcmp( pcLine , "id" ) ) { 290 291 XIntrospectionAccessRef ref = (*m_pInvokationRef)->getIntrospection(); 292 293 dumpIntrospectionToStream( ref , stderr ); 294 295 296 } 297 else if( ! strncmp( pcLine , "idv" , 3) ) { 298 try { 299 UsrAny any = (*m_pInvokationRef)->getValue( PCHAR_TO_USTRING( &(pcLine[4]) ) ); 300 dumpVarToStream( &(pcLine[4]) , any , stderr ); 301 } 302 catch(UnknownPropertyException& e ) { 303 fprintf( stderr, "UnknownPropertyException\n" ); 304 } 305 catch(IllegalArgumentException& e ) { 306 fprintf( stderr, "IllegalArgumentException\n" ); 307 } 308 } 309 else if( !strcmp( pcLine , "t" ) ) { 310 } 311 else if( !strcmp( pcLine , "h" ) ) { 312 fprintf( stderr , "\nvalid commands :\n" 313 "Go : g\n" 314 "StepOver : s\n" 315 "StepIn : si\n" 316 "StepOut : so\n" 317 "Set BreakPoint : sbp Line [ModuleName]\n" 318 "Remove BreakPoint : rbp [Line] [ModuleName]\n" 319 "via XDebugging Interface :\n" 320 " dump Variable : dv varname [CallStack]\n" 321 " set Variable : sv varname value [CallStack]\n" 322 "globals via XInvokation Interface :\n" 323 " dump Global vars : id\n" 324 " dump Variable : idv varname\n" 325 " set Variable : isv varname value\n" 326 "ContextInformation : ci\n" 327 "Dump callstack : d\n" 328 "Cancel : c (stops actual script)\n" 329 "Quit : q (exits debugger)\n" 330 ); 331 } 332 else if( ! strlen( pcLine ) ) { 333 } 334 else { 335 fprintf( stderr , "unknown command %s\n" , pcLine ); 336 } 337 } 338 } 339 340 void CmdDebugger::dumpIntrospectionToStream( const XIntrospectionAccessRef &ref, FILE *f ) 341 { 342 int i,iMax; 343 fprintf( stderr, "Callable Attributes (Methods) :\n" ); 344 Sequence<XIdlMethodRef> seq = ref->getMethods( 0 ); 345 iMax = seq.getLen(); 346 XIdlMethodRef *aRef = seq.getArray(); 347 for( i = 0; i < iMax ; i++ ) { 348 fprintf( f, " %s\n" , USTRING_TO_PCHAR( aRef[i]->getName( ) ) ); 349 } 350 351 fprintf( stderr, "Other attributes\n" ); 352 Sequence<Property> seqProp = ref->getProperties( 0 ); 353 iMax = seqProp.getLen(); 354 Property *aProp = seqProp.getArray(); 355 for( i = 0; i < iMax ; i ++ ) { 356 fprintf( f, " %s %s\n" , USTRING_TO_PCHAR( aProp[i].Type->getName() ), 357 USTRING_TO_PCHAR( aProp[i].Name ) ); 358 } 359 360 } 361 362 void CmdDebugger::dumpVarToStream( const char *pc , const UsrAny &aValue, FILE *f ) 363 { 364 TypeClass type = aValue.getReflection()->getTypeClass(); 365 366 if( TypeClass_INT == type ) { 367 fprintf( f, "INT32 %s : %d\n" , pc , aValue.getINT32() ); 368 } 369 else if( TypeClass_ENUM == type ) { 370 fprintf( f, "ENUM %s : %d\n", pc , aValue.getEnumAsINT32() ); 371 } 372 else if( TypeClass_STRING == type ) { 373 fprintf( f, "STRING %s : %s\n" , pc , USTRING_TO_PCHAR( aValue.getString()) ); 374 } 375 else if( TypeClass_BOOLEAN == type ) { 376 fprintf( f, "BOOL %s : %d\n", pc , aValue.getBOOL() ); 377 } 378 else if( TypeClass_CHAR == type ) { 379 fprintf( f, "char %s : %d\n", pc , ( INT32) aValue.getChar() ); 380 } 381 else if( TypeClass_SHORT == type ) { 382 fprintf( f, "INT16 %s : %d\n", pc , (INT32) aValue.getINT16()); 383 } 384 else if( TypeClass_LONG == type ) { 385 fprintf( f, "LONG %s : %d\n", pc , (INT32) aValue.getINT32()); 386 } 387 else if( TypeClass_UNSIGNED_SHORT == type ) { 388 fprintf( f, "UINT16 %s : %d\n", pc , (INT32) aValue.getUINT16() ); 389 } 390 else if( TypeClass_UNSIGNED_BYTE == type ) { 391 fprintf( f, "Byte %s : %d\n", pc , (INT32) aValue.getBYTE() ); 392 } 393 else if( TypeClass_UNSIGNED_INT == type ) { 394 fprintf( f, "UINT32 %s : %d\n", pc , aValue.getUINT32() ); 395 } 396 else if( TypeClass_FLOAT == type ) { 397 fprintf( f, "float %s : %f\n" , pc , aValue.getFloat() ); 398 } 399 else if( TypeClass_DOUBLE == type ) { 400 fprintf( f, "double %s : %f\n" , pc , aValue.getDouble() ); 401 } 402 else if( TypeClass_VOID == type ) { 403 fprintf( f, "void %s :\n" , pc ); 404 } 405 else if( TypeClass_INTERFACE == type ) { 406 // Check, what has been put in 407 if( aValue.getReflection() == XPropertySet_getReflection() ) { 408 // XPropertySet ! 409 XPropertySetRef *pRef = ( XPropertySetRef * ) aValue.get(); 410 XPropertySetInfoRef refInfo = (*pRef)->getPropertySetInfo(); 411 Sequence< Property > seq = refInfo->getProperties(); 412 int i,iMax = seq.getLen(); 413 414 Property *pArray; 415 pArray = seq.getArray(); 416 fprintf( stderr, "Property List :\n" ); 417 for( i = 0; i < iMax ; i ++ ) { 418 fprintf( f, "%s\t %s\n" , USTRING_TO_PCHAR(pArray[i].Type->getName()), 419 USTRING_TO_PCHAR( pArray[i].Name ) ); 420 } 421 } 422 else if( aValue.getReflection() == XInvokation_getReflection() ) { 423 XInvokationRef *pRef = ( XInvokationRef * ) aValue.get(); 424 XIntrospectionAccessRef refIntro = (*pRef)->getIntrospection(); 425 426 dumpIntrospectionToStream( refIntro, stderr ); 427 } 428 } 429 else if( TypeClass_SEQUENCE == type ) { 430 fprintf( f , "%s Sequence \n" , pc ); 431 String s( " " ); 432 s += pc; 433 SequenceReflection *pSeqRefl = ( SequenceReflection * ) aValue.getReflection(); 434 435 int i,iMax = pSeqRefl->getLen( aValue ); 436 437 for( i = 0 ; i < iMax ; i ++ ) { 438 dumpVarToStream( s.GetCharStr() , pSeqRefl->get( aValue , i ) , stderr ); 439 } 440 } 441 else { 442 fprintf( f, "%s : unknown %d\n" , pc , type ); 443 } 444 445 } 446 447 void CmdDebugger::detach() 448 { 449 OSL_ASSERT( m_pDebuggingRef ); 450 451 m_bIsRunning = FALSE; 452 m_pDebuggingRef = 0; 453 m_pEngineRef = 0; 454 m_pInvokationRef = 0; 455 } 456 457 // Methoden von XInterface 458 BOOL CmdDebugger::queryInterface( Uik aUik, XInterfaceRef & rOut ) 459 { 460 if( aUik == XEngineListener::getSmartUik() ) 461 rOut = (XEngineListener*)this; 462 else 463 return OWeakObject::queryInterface( aUik, rOut ); 464 return TRUE; 465 } 466 467 468 469 470 471 472 /* 473 * main. 474 */ 475 int __LOADONCALLAPI main (int argc, char **argv) 476 { 477 XMultiServiceFactoryRef xSMgr = createRegistryServiceManager(); 478 registerUsrServices( xSMgr ); 479 setProcessServiceManager( xSMgr ); 480 481 XInterfaceRef x = xSMgr->createInstance( L"stardiv.uno.repos.ImplementationRegistration" ); 482 XImplementationRegistrationRef xReg( x, USR_QUERY ); 483 sal_Char szBuf[1024]; 484 485 ORealDynamicLoader::computeModuleName( "pythonengine", szBuf, 1024 ); 486 UString aDllName( StringToOUString( szBuf, CHARSET_SYSTEM ) ); 487 xReg->registerImplementation( L"stardiv.loader.SharedLibrary", aDllName, XSimpleRegistryRef() ); 488 489 ORealDynamicLoader::computeModuleName( "aps", szBuf, 1024 ); 490 aDllName = UString( StringToOUString( szBuf, CHARSET_SYSTEM ) ); 491 xReg->registerImplementation( L"stardiv.loader.SharedLibrary", aDllName, XSimpleRegistryRef() ); 492 493 XInterfaceRef y = xSMgr->createInstance( L"stardiv.script.Python" ); 494 XEngineRef yEngine( y, USR_QUERY ); 495 496 x = xSMgr->createInstance( L"stardiv.script.Python" ); 497 XEngineRef xEngine( x, USR_QUERY ); 498 499 500 UString Script; 501 502 Sequence<UsrAny> args(3); 503 UsrAny *pArray = args.getArray(); 504 pArray[0].setString( L"Arg_0" ); 505 pArray[1].setString( L"Arg_1" ); 506 pArray[2].setString( L"Arg_2" ); 507 508 if( argc > 2) { 509 Script = StringToOUString( String( argv[2] ) , CHARSET_DONTKNOW ); 510 } 511 512 XInvokationRef xInvokation( x , USR_QUERY ); 513 XDebuggingRef xDebug( x , USR_QUERY ); 514 515 CmdDebugger *pDbg = new CmdDebugger( &xDebug , &xEngine , &xInvokation ); 516 517 XEngineListenerRef xDebugRef( (XEngineListener *) pDbg , USR_QUERY); 518 xEngine->addEngineListener( xDebugRef ); 519 520 521 if( argc >1 && ! strcmp( argv[1] , "1" ) ) { 522 fprintf( stderr, "one thread only\n" ); 523 Script = UString( L"print 'Hello World'\n" ); 524 xEngine->runAsync( Script , XInterfaceRef(), args , XEngineListenerRef() ); 525 } 526 else if( argc >1 && ! strcmp( argv[1] , "2" ) ) { 527 528 xEngine->runAsync( UString( L"x=1\nprint 1\n") , XInterfaceRef(), args , XEngineListenerRef() ); 529 xEngine->runAsync( UString( L"x=x+1\nprint 2\n") , XInterfaceRef(), args , XEngineListenerRef() ); 530 xEngine->runAsync( UString( L"x=x+1\nprint 3\n") , XInterfaceRef(), args , XEngineListenerRef()); 531 xEngine->runAsync( UString( L"x=x+1\nprint 4\n") , XInterfaceRef(), args , XEngineListenerRef() ); 532 533 534 535 } 536 else if( argc >1 && ! strcmp( argv[1] , "3" ) ) { 537 538 fprintf( stderr , "1st thread in engine y, next 5 threads in engine x\n" ); 539 yEngine->runAsync( UString( L"print 1\n") , XInterfaceRef(), args , XEngineListenerRef() ); 540 xEngine->runAsync( UString( L"print 2\n") , XInterfaceRef(), args , XEngineListenerRef() ); 541 xEngine->runAsync( UString( L"print 3\n") , XInterfaceRef(), args , XEngineListenerRef() ); 542 xEngine->runAsync( UString( L"print 4\n") , XInterfaceRef(), args , XEngineListenerRef()); 543 xEngine->runAsync( UString( L"print 5\n") , XInterfaceRef(), args , XEngineListenerRef()); 544 xEngine->runAsync( UString( L"print 6\n") , XInterfaceRef(), args , XEngineListenerRef()); 545 546 547 } 548 pDbg->cmdLine(); 549 550 xEngine->removeEngineListener( xDebugRef ); 551 552 xReg->revokeImplementation( aDllName, XSimpleRegistryRef() ); 553 554 fprintf( stderr, "main terminates\n" ); 555 return 0; 556 } 557 558