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 #include "precompiled_basic.hxx"
25 
26 #include "rtlproto.hxx"
27 #include "sbdiagnose.hxx"
28 
29 #include "basic/sbstar.hxx"
30 
31 #include <tools/debug.hxx>
32 #include <comphelper/flagguard.hxx>
33 
34 #ifdef DBG_UTIL
35 
36 static DbgChannelId nRestoreChannelId = 0;
37 static DbgChannelId nAssertionChannelId = 0;
38 static StarBASICRef xAssertionChannelBasic;
39 static String sCaptureFunctionName;
40 static bool bReportingAssertion = false;
41 
ResetCapturedAssertions()42 void ResetCapturedAssertions()
43 {
44 	if ( nRestoreChannelId != 0 )
45 	{
46 		DBG_INSTOUTERROR( nRestoreChannelId );
47 	}
48     nRestoreChannelId = 0;
49     xAssertionChannelBasic = NULL;
50     sCaptureFunctionName = String();
51     bReportingAssertion = false;
52 }
53 
DbgReportAssertion(const sal_Char * i_assertionMessage)54 void DbgReportAssertion( const sal_Char* i_assertionMessage )
55 {
56     if ( !xAssertionChannelBasic )
57     {
58         ResetCapturedAssertions();
59         return;
60     }
61 
62     // prevent infinite recursion
63     if ( bReportingAssertion )
64         return;
65     ::comphelper::FlagRestorationGuard aGuard( bReportingAssertion, true );
66 
67 	SbxArrayRef const xArguments( new SbxArray( SbxVARIANT ) );
68 	SbxVariableRef const xMessageText = new SbxVariable( SbxSTRING );
69     xMessageText->PutString( String::CreateFromAscii( i_assertionMessage ) );
70     xArguments->Put( xMessageText, 1 );
71 
72     ErrCode const nError = xAssertionChannelBasic->Call( sCaptureFunctionName, xArguments );
73     if ( ( nError & SbERR_METHOD_NOT_FOUND ) != 0 )
74         ResetCapturedAssertions();
75 }
76 
77 #endif
78 
79 /// capture assertions, route them to the given given Basic function
RTLFUNC(CaptureAssertions)80 RTLFUNC(CaptureAssertions)
81 {
82     (void)bWrite;
83 
84     // need exactly one argument
85 	if ( rPar.Count() != 2 )
86 	{
87 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
88 		return;
89 	}
90 
91 #ifdef DBG_UTIL
92     DBG_TESTSOLARMUTEX();
93 
94     String const sFunctionName = rPar.Get(1)->GetString();
95     if ( sFunctionName.Len() == 0 )
96     {
97         ResetCapturedAssertions();
98         return;
99     }
100 
101     if ( nAssertionChannelId == 0 )
102     {
103         // TODO: should we register a named channel at the VCL API, instead of an unnamed channel at the tools API?
104         // A named channel would mean it would appear in the nonpro-debug-options dialog
105         nAssertionChannelId = DbgRegisterUserChannel( &DbgReportAssertion );
106     }
107 
108     DbgChannelId const nCurrentChannelId = (DbgChannelId)DbgGetErrorOut();
109     if ( nCurrentChannelId != nAssertionChannelId )
110     {
111         // remember the current channel
112         nRestoreChannelId = nCurrentChannelId;
113 
114         // set the new channel
115         DBG_INSTOUTERROR( nAssertionChannelId );
116 
117         // ensure OSL assertions are captured, too
118         DbgData aData( *DbgGetData() );
119         aData.bHookOSLAssert = sal_True;
120         DbgUpdateOslHook( &aData );
121     }
122 
123     xAssertionChannelBasic = pBasic;
124     sCaptureFunctionName = sFunctionName;
125 #else
126     (void)pBasic;
127     (void)rPar;
128     (void)bWrite;
129 #endif
130 }
131 
132