Coverity: Core module errors fixed
[scilab.git] / scilab / modules / core / src / cpp / runner.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2011-2011 - DIGITEO - Bruno JOFRET
4  *  Copyright (C) 2014-2015 - Scilab Enterprises - Cedric Delamarre
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 #include "runner.hxx"
18 #include "threadmanagement.hxx"
19 #include "configvariable.hxx"
20 #include "debugmanager.hxx"
21
22 extern "C"
23 {
24 #include "BrowseVarManager.h"
25 #include "FileBrowserChDir.h"
26 #include "scicurdir.h"
27 #include "Scierror.h"
28 #include "InitializeJVM.h"
29 }
30
31 std::atomic<Runner*> StaticRunner::m_RunMe(nullptr);
32 std::atomic<bool> StaticRunner::m_bInterruptibleCommand(true);
33
34 static bool initialJavaHooks = false;
35
36 static void sendExecDoneSignal(Runner* _pRunner)
37 {
38     switch (_pRunner->getCommandOrigin())
39     {
40         case CONSOLE :
41         {
42             ThreadManagement::SendConsoleExecDoneSignal();
43             break;
44         }
45         case TCLSCI :
46         case NONE :
47         default :
48         {}
49     }
50 }
51
52 int StaticRunner::launch()
53 {
54     //set execution thread in java
55     if (!initialJavaHooks && getScilabMode() != SCILAB_NWNI)
56     {
57         initialJavaHooks = true;
58         // Execute the initial hooks registered in Scilab.java
59         ExecuteInitialHooks();
60     }
61
62     int iRet = 0;
63     // get the runner to execute
64     std::unique_ptr<Runner> runMe(getRunner());
65     // set if the current comment is interruptible
66     setInterruptibleCommand(runMe->isInterruptible());
67     debugger::DebuggerMagager* manager = debugger::DebuggerMagager::getInstance();
68
69     ConfigVariable::resetExecutionBreak();
70
71     int oldMode = ConfigVariable::getPromptMode();
72     symbol::Context* pCtx = symbol::Context::getInstance();
73     int scope = pCtx->getScopeLevel();
74
75     // a TCL command display nothing
76     int iOldPromptMode = 0;
77     if (runMe->getCommandOrigin() == TCLSCI)
78     {
79         iOldPromptMode = ConfigVariable::getPromptMode();
80         ConfigVariable::setPromptMode(-1);
81     }
82
83     try
84     {
85         int level = ConfigVariable::getRecursionLevel();
86         try
87         {
88             runMe->getProgram()->accept(*(runMe->getVisitor()));
89         }
90         catch (const ast::RecursionException& re)
91         {
92             // management of pause
93             if (ConfigVariable::getPauseLevel())
94             {
95                 ConfigVariable::DecreasePauseLevel();
96                 throw re;
97             }
98
99             //close opened scope during try
100             while (pCtx->getScopeLevel() > scope)
101             {
102                 pCtx->scope_end();
103             }
104
105             //decrease recursion to init value and close where
106             while (ConfigVariable::getRecursionLevel() > level)
107             {
108                 ConfigVariable::where_end();
109                 ConfigVariable::decreaseRecursion();
110             }
111
112             ConfigVariable::resetWhereError();
113             ConfigVariable::setPromptMode(oldMode);
114
115             //print msg about recursion limit and trigger an error
116             wchar_t sz[1024];
117             os_swprintf(sz, 1024, _W("Recursion limit reached (%d).\n").data(), ConfigVariable::getRecursionLimit());
118             throw ast::InternalError(sz);
119         }
120     }
121     catch (const ast::InternalError& se)
122     {
123         if (runMe->getCommandOrigin() == TCLSCI)
124         {
125             ConfigVariable::setPromptMode(iOldPromptMode);
126         }
127
128         std::wostringstream ostr;
129         ConfigVariable::whereErrorToString(ostr);
130         scilabErrorW(ostr.str().c_str());
131         scilabErrorW(se.GetErrorMessage().c_str());
132         ConfigVariable::resetWhereError();
133         iRet = 1;
134     }
135     catch (const ast::InternalAbort& ia)
136     {
137         if (runMe->getCommandOrigin() == TCLSCI)
138         {
139             ConfigVariable::setPromptMode(iOldPromptMode);
140         }
141
142         // management of pause
143         if (ConfigVariable::getPauseLevel())
144         {
145             ConfigVariable::DecreasePauseLevel();
146             throw ia;
147         }
148
149         // close all scope before return to console scope
150         symbol::Context* pCtx = symbol::Context::getInstance();
151         while (pCtx->getScopeLevel() > scope)
152         {
153             pCtx->scope_end();
154         }
155
156         // send the good signal about the end of execution
157         sendExecDoneSignal(runMe.get());
158
159         //clean debugger step flag if debugger is not interrupted ( end of debug )
160         manager->resetStep();
161         throw ia;
162     }
163
164     if (runMe->getCommandOrigin() == TCLSCI)
165     {
166         ConfigVariable::setPromptMode(iOldPromptMode);
167     }
168
169     if (getScilabMode() != SCILAB_NWNI && getScilabMode() != SCILAB_API)
170     {
171         char *cwd = NULL;
172         int err = 0;
173
174         UpdateBrowseVar();
175         cwd = scigetcwd(&err);
176         if (cwd)
177         {
178             FileBrowserChDir(cwd);
179             FREE(cwd);
180         }
181     }
182
183     // reset error state when new prompt occurs
184     ConfigVariable::resetError();
185
186     // send the good signal about the end of execution
187     sendExecDoneSignal(runMe.get());
188
189     //clean debugger step flag if debugger is not interrupted ( end of debug )
190     manager->resetStep();
191     return iRet;
192 }
193
194 void StaticRunner::setRunner(Runner* _RunMe)
195 {
196     m_RunMe = _RunMe;
197 }
198
199 Runner* StaticRunner::getRunner(void)
200 {
201     Runner* tmp = m_RunMe.exchange(nullptr);
202     ThreadManagement::SendAvailableRunnerSignal();
203     return tmp;
204 }
205
206 // return true if a Runner is already set in m_RunMe.
207 bool StaticRunner::isRunnerAvailable(void)
208 {
209     return m_RunMe.load() != nullptr;
210 }
211
212 void StaticRunner::setInterruptibleCommand(bool _bInterruptibleCommand)
213 {
214     m_bInterruptibleCommand = _bInterruptibleCommand;
215 }
216
217 bool StaticRunner::isInterruptibleCommand()
218 {
219     return m_bInterruptibleCommand;
220 }
221
222 command_origin_t StaticRunner::getCommandOrigin()
223 {
224     return m_RunMe.load()->getCommandOrigin();
225 }
226
227 void StaticRunner::execAndWait(ast::Exp* _theProgram, ast::RunVisitor *_visitor,
228                                bool /*_isPrioritaryThread*/, bool _isInterruptible, command_origin_t _iCommandOrigin)
229 {
230     if (isRunnerAvailable())
231     {
232         // wait for managenement of last Runner
233         ThreadManagement::WaitForAvailableRunnerSignal();
234     }
235
236     // lock runner to be sure we are waiting for
237     // "AwakeRunner" signal before start execution
238     ThreadManagement::LockRunner();
239     Runner *runMe = new Runner(_theProgram, _visitor, _iCommandOrigin, _isInterruptible);
240     setRunner(runMe);
241
242     ThreadManagement::SendRunMeSignal();
243     ThreadManagement::WaitForAwakeRunnerSignal();
244 }
245
246 bool StaticRunner::exec(ast::Exp* _theProgram, ast::RunVisitor *_visitor)
247 {
248     Runner *runMe = new Runner(_theProgram, _visitor);
249     setRunner(runMe);
250
251     try
252     {
253         launch();
254     }
255     catch (const ast::InternalAbort& /*ia*/)
256     {
257         //catch exit command in .start or .quit
258         return false;
259     }
260
261     return true;
262 }
263
264 void StaticRunner_launch(void)
265 {
266     StaticRunner::launch();
267 }
268
269 int StaticRunner_isRunnerAvailable(void)
270 {
271     return StaticRunner::isRunnerAvailable() ? 1 : 0;
272 }
273
274 int StaticRunner_isInterruptibleCommand(void)
275 {
276     return StaticRunner::isInterruptibleCommand() ? 1 : 0;
277 }
278
279 void StaticRunner_setInterruptibleCommand(int val)
280 {
281     StaticRunner::setInterruptibleCommand(val == 1);
282 }
283
284 command_origin_t StaticRunner_getCommandOrigin(void)
285 {
286     return StaticRunner::getCommandOrigin();
287 }