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