debugger: error in try/catch and errcatch fixed
[scilab.git] / scilab / modules / functions / sci_gateway / cpp / sci_execstr.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2006 - INRIA - Antoine ELIAS
4 *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13 *
14 */
15
16 //#include "AnalysisVisitor.hxx"
17 #include "parser.hxx"
18 #include "functions_gw.hxx"
19 #include "visitor_common.hxx"
20 #include "scilabWrite.hxx"
21 #include "configvariable.hxx"
22 #include "threadmanagement.hxx"
23
24 #include <memory>
25 #include <iostream>
26 #include <fstream>
27 #include <string>
28
29 extern "C"
30 {
31 #include "sci_malloc.h"
32 #include "os_string.h"
33 #include "Scierror.h"
34 #include "sciprint.h"
35 #include "localization.h"
36 #include "os_string.h"
37 }
38
39 #define MUTE_FLAG       L"n"
40 #define NO_MUTE_FLAG    L"m"
41
42 /*--------------------------------------------------------------------------*/
43 types::Function::ReturnValue sci_execstr(types::typed_list &in, int _iRetCount, types::typed_list &out)
44 {
45     int iErr            = 0;
46     bool bErrCatch              = false;
47     bool bMute          = false;
48     wchar_t* pstMsg     = NULL;
49     ast::Exp* pExp      = NULL;
50     wchar_t *pstCommand = NULL;
51     bool bSilentError   = ConfigVariable::isSilentError();
52     Parser parser;
53
54     if (in.size() < 1 || in.size() > 3)
55     {
56         Scierror(999, _("%s: Wrong number of input arguments: %d to %d expected.\n"), "execstr" , 1, 3);
57         return types::Function::Error;
58     }
59
60     //2nd parameter
61     if (in.size() > 1)
62     {
63         //errcatch
64         if (in[1]->isString() == false || in[1]->getAs<types::String>()->getSize() != 1)
65         {
66             Scierror(999, _("%s: Wrong type for input argument #%d: string expected.\n"), "execstr", 2);
67             return types::Function::Error;
68         }
69
70         types::String* pS = in[1]->getAs<types::String>();
71         if (os_wcsicmp(pS->get(0), L"errcatch") == 0)
72         {
73             bErrCatch = true;
74         }
75         else
76         {
77             Scierror(999, _("%s: Wrong value for input argument #%d: 'errcatch' expected.\n"), "execstr", 2);
78             return types::Function::Error;
79         }
80
81         bMute = true;
82     }
83
84     //3rd parameter
85     if (in.size() == 3)
86     {
87         if (in[2]->isString() == false || in[2]->getAs<types::String>()->getSize() != 1)
88         {
89             Scierror(999, _("%s: Wrong type for input argument #%d: string expected.\n"), "execstr", 3);
90             return types::Function::Error;
91         }
92
93         if (os_wcsicmp(in[2]->getAs<types::String>()->get(0), MUTE_FLAG) == 0)
94         {
95             bMute = true;
96         }
97         else if (os_wcsicmp(in[2]->getAs<types::String>()->get(0), NO_MUTE_FLAG) == 0)
98         {
99             bMute = false;
100         }
101         else
102         {
103             Scierror(999, _("%s: Wrong value for input argument #%d: '%s' or '%s' expected.\n"), "execstr", 3, MUTE_FLAG, NO_MUTE_FLAG);
104             return types::Function::Error;
105         }
106     }
107
108     //1st argument
109     if (in[0]->isDouble() && in[0]->getAs<types::Double>()->getSize() == 0)
110     {
111         // execstr([])
112         out.push_back(types::Double::Empty());
113         return types::Function::OK;
114     }
115
116     if (in[0]->isString() == false || (in[0]->getAs<types::String>()->getRows() != 1 && in[0]->getAs<types::String>()->getCols() != 1))
117     {
118         Scierror(999, _("%s: Wrong type for input argument #%d: Vector of strings expected.\n"), "execstr", 1);
119         return types::Function::Error;
120     }
121
122     types::String* pS = in[0]->getAs<types::String>();
123     int iTotalLen = pS->getSize(); //add \n after each string
124     for (int i = 0 ; i < pS->getSize() ; i++)
125     {
126         iTotalLen += (int)wcslen(pS->get(i));
127     }
128
129     pstCommand = (wchar_t*)MALLOC(sizeof(wchar_t) * (iTotalLen + 1));//+1 for null termination
130
131     for (int i = 0, iPos = 0 ; i < pS->getSize() ; i++)
132     {
133         wcscpy(pstCommand + iPos, pS->get(i));
134         iPos = (int)wcslen(pstCommand);
135         pstCommand[iPos++] = L'\n';
136         pstCommand[iPos] = 0;
137     }
138
139     // add execstr in list of macro called
140     // to manage line displayed when error occurred.
141     ConfigVariable::macroFirstLine_begin(1);
142
143     ThreadManagement::LockParser();
144     parser.parse(pstCommand);
145     FREE(pstCommand);
146     if (parser.getExitStatus() !=  Parser::Succeded)
147     {
148         if (bErrCatch)
149         {
150             out.push_back(new types::Double(999));
151             //to lock last error information
152             ConfigVariable::setLastErrorCall();
153             ConfigVariable::setLastErrorMessage(parser.getErrorMessage());
154             ConfigVariable::setLastErrorNumber(999);
155             ThreadManagement::UnlockParser();
156             ConfigVariable::macroFirstLine_end();
157             return types::Function::OK;
158         }
159         else
160         {
161             char* pst = wide_string_to_UTF8(parser.getErrorMessage());
162             Scierror(999, "%s", pst);
163             FREE(pst);
164             ThreadManagement::UnlockParser();
165             ConfigVariable::macroFirstLine_end();
166             return types::Function::Error;
167         }
168     }
169
170     if (ConfigVariable::getSerialize())
171     {
172         ast::Exp* temp = parser.getTree();
173         if (ConfigVariable::getTimed())
174         {
175             pExp = callTyper(temp, L"execstr");
176         }
177         else
178         {
179             pExp = callTyper(temp);
180         }
181
182         delete temp;
183     }
184     else
185     {
186         pExp = parser.getTree();
187     }
188
189     ThreadManagement::UnlockParser();
190
191     if (pExp == NULL)
192     {
193         return types::Function::Error;
194     }
195
196     //save current prompt mode
197     int iPromptMode = ConfigVariable::getPromptMode();
198     ConfigVariable::setPromptMode(-1);
199
200     if (ConfigVariable::getAnalyzerOptions() == 1)
201     {
202         //analysis::AnalysisVisitor analysis;
203         //pExp->accept(analysis);
204         //ast::DebugVisitor debugMe;
205         //pExp->accept(debugMe);
206     }
207
208     ast::SeqExp* pSeqExp = pExp->getAs<ast::SeqExp>();
209     std::unique_ptr<ast::ConstVisitor> run(ConfigVariable::getDefaultVisitor());
210     ConfigVariable::setSilentError(bErrCatch);
211     try
212     {
213         symbol::Context* pCtx = symbol::Context::getInstance();
214         int scope = pCtx->getScopeLevel();
215         int level = ConfigVariable::getRecursionLevel();
216         try
217         {
218             pSeqExp->accept(*run);
219         }
220         catch (const ast::RecursionException& /* re */)
221         {
222             ConfigVariable::setSilentError(bSilentError);
223
224             //close opened scope during try
225             while (pCtx->getScopeLevel() > scope)
226             {
227                 pCtx->scope_end();
228             }
229
230             //decrease recursion to init value
231             while (ConfigVariable::getRecursionLevel() > level)
232             {
233                 ConfigVariable::where_end();
234                 ConfigVariable::decreaseRecursion();
235             }
236
237             //print msg about recursion limit and trigger an error
238             wchar_t sz[1024];
239             os_swprintf(sz, 1024, _W("Recursion limit reached (%d).\n").data(), ConfigVariable::getRecursionLimit());
240             throw ast::InternalError(sz);
241         }
242     }
243     catch (const ast::InternalError& ie)
244     {
245         if (bErrCatch == false)
246         {
247             delete pExp;
248             ConfigVariable::macroFirstLine_end();
249             ConfigVariable::setPromptMode(iPromptMode);
250             ConfigVariable::setSilentError(bSilentError);
251             throw ie;
252         }
253
254         if (bMute == false)
255         {
256             scilabForcedWriteW(ie.GetErrorMessage().c_str());
257         }
258
259         ConfigVariable::resetWhereError();
260         iErr = ConfigVariable::getLastErrorNumber();
261     }
262
263     if (bErrCatch)
264     {
265         out.push_back(new types::Double(iErr));
266         //to lock last error information
267         ConfigVariable::setLastErrorCall();
268         // allow print
269         ConfigVariable::resetError();
270     }
271
272     ConfigVariable::macroFirstLine_end();
273     ConfigVariable::setPromptMode(iPromptMode);
274     ConfigVariable::setSilentError(bSilentError);
275
276     delete pExp;
277     return types::Function::OK;
278 }
279 /*--------------------------------------------------------------------------*/