1 /*************************************************************************
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3  *
4  * Copyright 2000, 2011 Oracle and/or its affiliates.
5  *
6  * OpenOffice.org - a multi-platform office productivity suite
7  *
8  * This file is part of OpenOffice.org.
9  *
10  * OpenOffice.org is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Lesser General Public License version 3
12  * only, as published by the Free Software Foundation.
13  *
14  * OpenOffice.org is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Lesser General Public License version 3 for more details
18  * (a copy is included in the LICENSE file that accompanied this code).
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * version 3 along with OpenOffice.org.  If not, see
22  * <http://www.openoffice.org/license.html>
23  * for a copy of the LGPLv3 License.
24  *
25  ************************************************************************/
26 
27 #include "precompiled_basic.hxx"
28 
29 #include "rtlproto.hxx"
30 #include "sbdiagnose.hxx"
31 
32 #include "basic/sbstar.hxx"
33 
34 #include <tools/debug.hxx>
35 #include <comphelper/flagguard.hxx>
36 
37 #ifdef DBG_UTIL
38 
39 static DbgChannelId nRestoreChannelId = 0;
40 static DbgChannelId nAssertionChannelId = 0;
41 static StarBASICRef xAssertionChannelBasic;
42 static String sCaptureFunctionName;
43 static bool bReportingAssertion = false;
44 
45 void ResetCapturedAssertions()
46 {
47 	if ( nRestoreChannelId != 0 )
48 	{
49 		DBG_INSTOUTERROR( nRestoreChannelId );
50 	}
51     nRestoreChannelId = 0;
52     xAssertionChannelBasic = NULL;
53     sCaptureFunctionName = String();
54     bReportingAssertion = false;
55 }
56 
57 void DbgReportAssertion( const sal_Char* i_assertionMessage )
58 {
59     if ( !xAssertionChannelBasic )
60     {
61         ResetCapturedAssertions();
62         return;
63     }
64 
65     // prevent infinite recursion
66     if ( bReportingAssertion )
67         return;
68     ::comphelper::FlagRestorationGuard aGuard( bReportingAssertion, true );
69 
70 	SbxArrayRef const xArguments( new SbxArray( SbxVARIANT ) );
71 	SbxVariableRef const xMessageText = new SbxVariable( SbxSTRING );
72     xMessageText->PutString( String::CreateFromAscii( i_assertionMessage ) );
73     xArguments->Put( xMessageText, 1 );
74 
75     ErrCode const nError = xAssertionChannelBasic->Call( sCaptureFunctionName, xArguments );
76     if ( ( nError & SbERR_METHOD_NOT_FOUND ) != 0 )
77         ResetCapturedAssertions();
78 }
79 
80 #endif
81 
82 /// capture assertions, route them to the given given Basic function
83 RTLFUNC(CaptureAssertions)
84 {
85     (void)bWrite;
86 
87     // need exactly one argument
88 	if ( rPar.Count() != 2 )
89 	{
90 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
91 		return;
92 	}
93 
94 #ifdef DBG_UTIL
95     DBG_TESTSOLARMUTEX();
96 
97     String const sFunctionName = rPar.Get(1)->GetString();
98     if ( sFunctionName.Len() == 0 )
99     {
100         ResetCapturedAssertions();
101         return;
102     }
103 
104     if ( nAssertionChannelId == 0 )
105     {
106         // TODO: should we register a named channel at the VCL API, instead of an unnamed channel at the tools API?
107         // A named channel would mean it would appear in the nonpro-debug-options dialog
108         nAssertionChannelId = DbgRegisterUserChannel( &DbgReportAssertion );
109     }
110 
111     DbgChannelId const nCurrentChannelId = (DbgChannelId)DbgGetErrorOut();
112     if ( nCurrentChannelId != nAssertionChannelId )
113     {
114         // remember the current channel
115         nRestoreChannelId = nCurrentChannelId;
116 
117         // set the new channel
118         DBG_INSTOUTERROR( nAssertionChannelId );
119 
120         // ensure OSL assertions are captured, too
121         DbgData aData( *DbgGetData() );
122         aData.bHookOSLAssert = sal_True;
123         DbgUpdateOslHook( &aData );
124     }
125 
126     xAssertionChannelBasic = pBasic;
127     sCaptureFunctionName = sFunctionName;
128 #else
129     (void)pBasic;
130     (void)rPar;
131     (void)bWrite;
132 #endif
133 }
134 
135