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