1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 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/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 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 . 18 */ 19 20 #pragma once 21 22 #include <basic/sberrors.hxx> 23 #include <basic/sbmeth.hxx> 24 #include <basic/sbstar.hxx> 25 #include <basic/sbx.hxx> 26 27 #include <rtl/ustring.hxx> 28 #include <com/sun/star/uno/Sequence.hxx> 29 #include <osl/file.hxx> 30 #include <i18nlangtag/lang.h> 31 32 #include <cmath> 33 #include <vector> 34 #include <memory> 35 #include <com/sun/star/lang/XComponent.hpp> 36 #include <com/sun/star/container/XEnumeration.hpp> 37 #include <com/sun/star/container/XIndexAccess.hpp> 38 #include <unotools/localedatawrapper.hxx> 39 #include <o3tl/deleter.hxx> 40 #include <o3tl/typed_flags_set.hxx> 41 42 class SbiInstance; // active StarBASIC process 43 class SbiRuntime; // active StarBASIC procedure instance 44 45 struct SbiArgv; // Argv stack element 46 struct SbiGosub; // GOSUB stack element 47 class SbiImage; // Code-Image 48 class SbiIoSystem; 49 class SbiDdeControl; 50 class SbiDllMgr; 51 class SvNumberFormatter; // time/date functions 52 enum class SbiImageFlags; 53 54 enum class ForType { 55 To, 56 EachArray, 57 EachCollection, 58 EachXEnumeration, 59 EachXIndexAccess, 60 Error, 61 }; 62 63 struct SbiForStack { // for/next stack: 64 SbiForStack* pNext; // Chain 65 SbxVariableRef refVar; // loop variable 66 SbxVariableRef refEnd; // end expression / for each: Array/BasicCollection object 67 SbxVariableRef refInc; // increment expression 68 69 // For each support 70 ForType eForType; 71 sal_Int32 nCurCollectionIndex; 72 std::unique_ptr<sal_Int32[]> 73 pArrayCurIndices; 74 std::unique_ptr<sal_Int32[]> 75 pArrayLowerBounds; 76 std::unique_ptr<sal_Int32[]> 77 pArrayUpperBounds; 78 css::uno::Reference< css::container::XEnumeration > xEnumeration; 79 css::uno::Reference<css::container::XIndexAccess> xIndexAccess; 80 81 SbiForStack() 82 : pNext(nullptr) 83 , eForType(ForType::To) 84 , nCurCollectionIndex(0) 85 {} 86 }; 87 88 #define MAXRECURSION 500 //to prevent dead-recursions 89 90 enum class SbAttributes { 91 NONE = 0x0000, 92 READONLY = 0x0001, 93 HIDDEN = 0x0002, 94 DIRECTORY = 0x0010 95 }; 96 97 namespace o3tl 98 { 99 template<> struct typed_flags<SbAttributes> : is_typed_flags<SbAttributes, 0x13> {}; 100 } 101 102 class WildCard; 103 104 class SbiRTLData 105 { 106 public: 107 108 std::unique_ptr<osl::Directory> pDir; 109 SbAttributes nDirFlags; 110 short nCurDirPos; 111 112 OUString sFullNameToBeChecked; 113 std::unique_ptr<WildCard> pWildCard; 114 115 css::uno::Sequence< OUString > aDirSeq; 116 117 SbiRTLData(); 118 ~SbiRTLData(); 119 }; 120 121 // The instance matches a running StarBASIC. Many basics running at the same 122 // time are managed by chained instances. There is all the data that only lives 123 // when the BASIC is living too, like the I/O-system. 124 125 typedef std::vector< css::uno::Reference< css::lang::XComponent > > ComponentVector_t; 126 127 128 class SbiInstance 129 { 130 friend class SbiRuntime; 131 132 SbiRTLData aRTLData; 133 134 // file system 135 std::unique_ptr<SbiIoSystem, o3tl::default_delete<SbiIoSystem>> pIosys; 136 // DDE 137 std::unique_ptr<SbiDdeControl> pDdeCtrl; 138 // DLL-Calls (DECLARE) 139 std::unique_ptr<SbiDllMgr> pDllMgr; 140 std::shared_ptr<SvNumberFormatter> pNumberFormatter; 141 StarBASIC* pBasic; 142 LanguageType meFormatterLangType; 143 DateOrder meFormatterDateOrder; 144 sal_uInt32 nStdDateIdx, nStdTimeIdx, nStdDateTimeIdx; 145 146 ErrCode nErr; 147 OUString aErrorMsg; // last error message for $ARG 148 sal_Int32 nErl; // current error line 149 bool bReschedule; // Flag: sal_True = Reschedule in main loop 150 bool bCompatibility; // Flag: sal_True = VBA runtime compatibility mode 151 152 ComponentVector_t ComponentVector; 153 public: 154 SbiRuntime* pRun; // Call-Stack 155 156 // #31460 new concept for StepInto/Over/Out, 157 // explanation see runtime.cxx at SbiInstance::CalcBreakCallLevel() 158 sal_uInt16 nCallLvl; 159 sal_uInt16 nBreakCallLvl; 160 void CalcBreakCallLevel( BasicDebugFlags nFlags ); 161 162 SbiInstance( StarBASIC* ); 163 ~SbiInstance(); 164 165 void Error( ErrCode ); // trappable Error 166 void Error( ErrCode, const OUString& rMsg ); // trappable Error with message 167 void ErrorVB( sal_Int32 nVBNumber, const OUString& rMsg ); 168 void setErrorVB( sal_Int32 nVBNumber ); 169 void FatalError( ErrCode ); // non-trappable Error 170 void FatalError( ErrCode, const OUString& ); // non-trappable Error 171 void Abort(); // with current error code 172 173 void Stop(); 174 ErrCode const & GetErr() const { return nErr; } 175 const OUString& GetErrorMsg() const { return aErrorMsg; } 176 sal_Int32 GetErl() const { return nErl; } 177 void EnableReschedule( bool bEnable ) { bReschedule = bEnable; } 178 bool IsReschedule() const { return bReschedule; } 179 void EnableCompatibility( bool bEnable ) { bCompatibility = bEnable; } 180 bool IsCompatibility() const { return bCompatibility; } 181 182 ComponentVector_t& getComponentVector() { return ComponentVector; } 183 184 SbMethod* GetCaller( sal_uInt16 ); 185 SbModule* GetActiveModule(); 186 187 SbiIoSystem* GetIoSystem() { return pIosys.get(); } 188 SbiDdeControl* GetDdeControl() { return pDdeCtrl.get(); } 189 StarBASIC* GetBasic() { return pBasic; } 190 SbiDllMgr* GetDllMgr(); 191 SbiRTLData& GetRTLData() { return aRTLData; } 192 193 std::shared_ptr<SvNumberFormatter> const & GetNumberFormatter(); 194 sal_uInt32 GetStdDateIdx() const { return nStdDateIdx; } 195 sal_uInt32 GetStdTimeIdx() const { return nStdTimeIdx; } 196 sal_uInt32 GetStdDateTimeIdx() const { return nStdDateTimeIdx; } 197 198 // offer NumberFormatter also static 199 static std::shared_ptr<SvNumberFormatter> PrepareNumberFormatter( sal_uInt32 &rnStdDateIdx, 200 sal_uInt32 &rnStdTimeIdx, sal_uInt32 &rnStdDateTimeIdx, 201 LanguageType const * peFormatterLangType=nullptr, DateOrder const * peFormatterDateOrder=nullptr ); 202 }; 203 204 // There's one instance of this class for every executed sub-program. 205 // This instance is the heart of the BASIC-machine and contains only local data. 206 207 class SbiRuntime 208 { 209 friend void SbRtl_CallByName( StarBASIC* pBasic, SbxArray& rPar, bool bWrite ); 210 211 typedef void( SbiRuntime::*pStep0 )(); 212 typedef void( SbiRuntime::*pStep1 )( sal_uInt32 nOp1 ); 213 typedef void( SbiRuntime::*pStep2 )( sal_uInt32 nOp1, sal_uInt32 nOp2 ); 214 static const pStep0 aStep0[]; // opcode-table group 0 215 static const pStep1 aStep1[]; 216 static const pStep2 aStep2[]; 217 218 StarBASIC& rBasic; // StarBASIC instance 219 SbiInstance* pInst; // current thread 220 SbModule* pMod; // current module 221 SbMethod* pMeth; // method instance 222 SbiIoSystem* pIosys; // I/O-System 223 const SbiImage* pImg; // Code-Image 224 SbxArrayRef refExprStk; // expression stack 225 SbxArrayRef refCaseStk; // CASE expression stack 226 SbxArrayRef refRedimpArray; // Array saved to use for REDIM PRESERVE 227 SbxVariableRef refRedim; // Array saved to use for REDIM 228 SbxVariableRef xDummyVar; // substitute for variables that weren't found 229 SbxVariable* mpExtCaller; // Caller ( external - e.g. button name, shape, range object etc. - only in vba mode ) 230 SbiForStack* pForStk; // FOR/NEXT-Stack 231 sal_uInt16 nExprLvl; // depth of the expr-stack 232 sal_uInt16 nForLvl; // #118235: Maintain for level 233 const sal_uInt8* pCode; // current Code-Pointer 234 const sal_uInt8* pStmnt; // beginning of the last statement 235 const sal_uInt8* pError; // address of the current error handler 236 const sal_uInt8* pRestart; // restart-address 237 const sal_uInt8* pErrCode; // restart-address RESUME NEXT 238 const sal_uInt8* pErrStmnt; // restart-address RESUME 0 239 OUString aLibName; // Lib-name for declare-call 240 SbxArrayRef refParams; // current procedure parameters 241 SbxArrayRef refLocals; // local variable 242 SbxArrayRef refArgv; 243 // #74254, one refSaveObj is not enough! new: pRefSaveList (see above) 244 short nArgc; 245 bool bRun; 246 bool bError; // true: handle errors 247 bool bInError; // true: in an error handler 248 bool bBlocked; // true: blocked by next call level, #i48868 249 bool bVBAEnabled; 250 BasicDebugFlags nFlags; // Debugging-Flags 251 ErrCode nError; 252 sal_uInt16 nOps; // opcode counter 253 sal_uInt32 m_nLastTime; 254 255 std::vector<SbxVariableRef> aRefSaved; // #74254 save temporary references 256 std::vector<SbiGosub> pGosubStk; // GOSUB stack 257 std::vector<SbiArgv> pArgvStk; // ARGV-Stack 258 259 260 SbxVariable* FindElement 261 ( SbxObject* pObj, sal_uInt32 nOp1, sal_uInt32 nOp2, ErrCode, bool bLocal, bool bStatic = false ); 262 void SetupArgs( SbxVariable*, sal_uInt32 ); 263 SbxVariable* CheckArray( SbxVariable* ); 264 265 void PushVar( SbxVariable* ); 266 SbxVariableRef PopVar(); 267 SbxVariable* GetTOS(); 268 void TOSMakeTemp(); 269 void ClearExprStack(); 270 271 void PushGosub( const sal_uInt8* ); 272 void PopGosub(); 273 274 void PushArgv(); 275 void PopArgv(); 276 void ClearArgvStack(); 277 278 void PushFor(); 279 void PushForEach(); 280 void PopFor(); 281 void ClearForStack(); 282 283 void StepArith( SbxOperator ); 284 void StepUnary( SbxOperator ); 285 void StepCompare( SbxOperator ); 286 287 void SetParameters( SbxArray* ); 288 289 // HAS TO BE IMPLEMENTED SOME TIME 290 void DllCall( std::u16string_view, std::u16string_view, SbxArray*, SbxDataType, bool ); 291 292 // #56204 swap out DIM-functionality into help method (step0.cxx) 293 void DimImpl(const SbxVariableRef& refVar); 294 bool EvaluateTopOfStackAsBool(); 295 296 static bool implIsClass( SbxObject const * pObj, const OUString& aClass ); 297 298 void StepSETCLASS_impl( sal_uInt32 nOp1, bool bHandleDflt ); 299 300 // the following routines are called by the single 301 // stepper and implement the single opcodes 302 void StepNOP(), StepEXP(), StepMUL(), StepDIV(); 303 void StepMOD(), StepPLUS(), StepMINUS(), StepNEG(); 304 void StepEQ(), StepNE(), StepLT(), StepGT(); 305 void StepLE(), StepGE(), StepIDIV(), StepAND(); 306 void StepOR(), StepXOR(), StepEQV(), StepIMP(); 307 void StepNOT(), StepCAT(), StepLIKE(), StepIS(); 308 void StepARGC(); 309 void StepARGV(), StepINPUT(), StepLINPUT(), StepSTOP(); 310 void StepGET(), StepSET(), StepVBASET(), StepPUT(), StepPUTC(); 311 void StepSET_Impl( SbxVariableRef& refVal, SbxVariableRef& refVar, bool bDefaultHandling = false ); 312 void StepDIM(), StepREDIM(), StepREDIMP(), StepERASE(); 313 void StepINITFOR(), StepNEXT(), StepERROR(), StepINITFOREACH(); 314 void StepCASE(), StepENDCASE(), StepSTDERROR(); 315 void StepNOERROR(), StepCHANNEL(), StepCHANNEL0(), StepPRINT(); 316 void StepPRINTF(), StepWRITE(), StepRENAME(), StepPROMPT(); 317 void StepRESTART(), StepEMPTY(), StepLEAVE(); 318 void StepLSET(), StepRSET(), StepREDIMP_ERASE(), StepERASE_CLEAR(); 319 void StepARRAYACCESS(), StepBYVAL(); 320 // all opcodes with one operand 321 void StepLOADNC( sal_uInt32 ), StepLOADSC( sal_uInt32 ), StepLOADI( sal_uInt32 ); 322 void StepARGN( sal_uInt32 ), StepBASED( sal_uInt32 ), StepPAD( sal_uInt32 ); 323 void StepJUMP( sal_uInt32 ), StepJUMPT( sal_uInt32 ); 324 void StepJUMPF( sal_uInt32 ), StepONJUMP( sal_uInt32 ); 325 void StepGOSUB( sal_uInt32 ), StepRETURN( sal_uInt32 ); 326 void StepTESTFOR( sal_uInt32 ), StepCASETO( sal_uInt32 ), StepERRHDL( sal_uInt32 ); 327 void StepRESUME( sal_uInt32 ), StepSETCLASS( sal_uInt32 ), StepVBASETCLASS( sal_uInt32 ), StepTESTCLASS( sal_uInt32 ), StepLIB( sal_uInt32 ); 328 bool checkClass_Impl( const SbxVariableRef& refVal, const OUString& aClass, bool bRaiseErrors, bool bDefault ); 329 void StepCLOSE( sal_uInt32 ), StepPRCHAR( sal_uInt32 ), StepARGTYP( sal_uInt32 ); 330 // all opcodes with two operands 331 void StepRTL( sal_uInt32, sal_uInt32 ), StepPUBLIC( sal_uInt32, sal_uInt32 ), StepPUBLIC_P( sal_uInt32, sal_uInt32 ); 332 void StepPUBLIC_Impl( sal_uInt32, sal_uInt32, bool bUsedForClassModule ); 333 void StepFIND_Impl( SbxObject* pObj, sal_uInt32 nOp1, sal_uInt32 nOp2, ErrCode, bool bStatic = false ); 334 void StepFIND( sal_uInt32, sal_uInt32 ), StepELEM( sal_uInt32, sal_uInt32 ); 335 void StepGLOBAL( sal_uInt32, sal_uInt32 ), StepLOCAL( sal_uInt32, sal_uInt32 ); 336 void StepPARAM( sal_uInt32, sal_uInt32), StepCREATE( sal_uInt32, sal_uInt32 ); 337 void StepCALL( sal_uInt32, sal_uInt32 ), StepCALLC( sal_uInt32, sal_uInt32 ); 338 void StepCASEIS( sal_uInt32, sal_uInt32 ), StepSTMNT( sal_uInt32, sal_uInt32 ); 339 SbxVariable* StepSTATIC_Impl( 340 OUString const & aName, SbxDataType t, sal_uInt32 nOp2 ); 341 void StepOPEN( sal_uInt32, sal_uInt32 ), StepSTATIC( sal_uInt32, sal_uInt32 ); 342 void StepTCREATE(sal_uInt32,sal_uInt32), StepDCREATE(sal_uInt32,sal_uInt32); 343 void StepGLOBAL_P( sal_uInt32, sal_uInt32 ),StepFIND_G( sal_uInt32, sal_uInt32 ); 344 void StepDCREATE_REDIMP(sal_uInt32,sal_uInt32), StepDCREATE_IMPL(sal_uInt32,sal_uInt32); 345 void StepFIND_CM( sal_uInt32, sal_uInt32 ); 346 void StepFIND_STATIC( sal_uInt32, sal_uInt32 ); 347 static void implHandleSbxFlags( SbxVariable* pVar, SbxDataType t, sal_uInt32 nOp2 ); 348 public: 349 void SetVBAEnabled( bool bEnabled ); 350 bool IsImageFlag( SbiImageFlags n ) const; 351 sal_uInt16 GetBase() const; 352 sal_Int32 nLine,nCol1,nCol2; 353 SbiRuntime* pNext; // Stack-Chain 354 355 // tdf#79426, tdf#125180 - adds the information about a missing parameter 356 static void SetIsMissing( SbxVariable* ); 357 // tdf#79426, tdf#125180 - checks if a variable contains the information about a missing parameter 358 static bool IsMissing( SbxVariable*, sal_uInt16 ); 359 360 SbiRuntime( SbModule*, SbMethod*, sal_uInt32 ); 361 ~SbiRuntime(); 362 void Error( ErrCode, bool bVBATranslationAlreadyDone = false ); // set error if != 0 363 void Error( ErrCode, const OUString& ); // set error if != 0 364 void FatalError( ErrCode ); // error handling = standard, set error 365 void FatalError( ErrCode, const OUString& ); // error handling = standard, set error 366 static sal_Int32 translateErrorToVba( ErrCode nError, OUString& rMsg ); 367 bool Step(); // single step (one opcode) 368 void Stop() { bRun = false; } 369 void block() { bBlocked = true; } 370 void unblock() { bBlocked = false; } 371 SbModule* GetModule() { return pMod; } 372 BasicDebugFlags GetDebugFlags() const { return nFlags; } 373 void SetDebugFlags( BasicDebugFlags nFl ) { nFlags = nFl; } 374 SbMethod* GetCaller() { return pMeth;} 375 SbxVariable* GetExternalCaller(){ return mpExtCaller; } 376 377 SbiForStack* FindForStackItemForCollection( class BasicCollection const * pCollection ); 378 379 SbxBase* FindElementExtern( const OUString& rName ); 380 static bool isVBAEnabled(); 381 382 }; 383 384 inline void checkArithmeticOverflow( double d ) 385 { 386 if( !std::isfinite( d ) ) 387 StarBASIC::Error( ERRCODE_BASIC_MATH_OVERFLOW ); 388 } 389 390 inline void checkArithmeticOverflow( SbxVariable const * pVar ) 391 { 392 if( pVar->GetType() == SbxDOUBLE ) 393 { 394 double d = pVar->GetDouble(); 395 checkArithmeticOverflow( d ); 396 } 397 } 398 399 400 StarBASIC* GetCurrentBasic( StarBASIC* pRTBasic ); 401 402 // Returns true if UNO is available, otherwise the old 403 // file system implementation has to be used 404 // (Implemented in iosys.cxx) 405 bool hasUno(); 406 407 // Converts possibly relative paths to absolute paths 408 // according to the setting done by ChDir/ChDrive 409 // (Implemented in methods.cxx) 410 OUString getFullPath( const OUString& aRelPath ); 411 412 // Implementation of StepRENAME with UCB 413 // (Implemented in methods.cxx, so step0.cxx 414 // has not to be infected with UNO) 415 void implStepRenameUCB( const OUString& aSource, const OUString& aDest ); 416 417 void implStepRenameOSL( const OUString& aSource, const OUString& aDest ); 418 bool IsBaseIndexOne(); 419 420 void removeDimAsNewRecoverItem( SbxVariable* pVar ); 421 422 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 423
