ce47ffa2eda34450c0ca7de93854104ca8fe1545
[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 <string.h>
14 //#include "AnalysisVisitor.hxx"
15 #include "parser.hxx"
16 #include "functions_gw.hxx"
17 #include "visitor_common.hxx"
18 #include "scilabWrite.hxx"
19 #include "configvariable.hxx"
20 #include "threadmanagement.hxx"
21
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: A 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: A 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     ThreadManagement::LockParser();
136     parser.parse(pstCommand);
137     FREE(pstCommand);
138     if (parser.getExitStatus() !=  Parser::Succeded)
139     {
140         if (bErrCatch)
141         {
142             out.push_back(new types::Double(999));
143             //to lock last error information
144             ConfigVariable::setLastErrorCall();
145             ConfigVariable::setLastErrorMessage(parser.getErrorMessage());
146             ConfigVariable::setLastErrorNumber(999);
147             ThreadManagement::UnlockParser();
148             return types::Function::OK;
149         }
150         else
151         {
152             char* pst = wide_string_to_UTF8(parser.getErrorMessage());
153             Scierror(999, "%s", pst);
154             FREE(pst);
155             ThreadManagement::UnlockParser();
156             return types::Function::Error;
157         }
158     }
159
160     if (ConfigVariable::getSerialize())
161     {
162         ast::Exp* temp = parser.getTree();
163         if (ConfigVariable::getTimed())
164         {
165             pExp = callTyper(temp, L"execstr");
166         }
167         else
168         {
169             pExp = callTyper(temp);
170         }
171
172         delete temp;
173     }
174     else
175     {
176         pExp = parser.getTree();
177     }
178
179     ThreadManagement::UnlockParser();
180
181     if (pExp == NULL)
182     {
183         return types::Function::Error;
184     }
185
186     //save current prompt mode
187     int iPromptMode = ConfigVariable::getPromptMode();
188     ConfigVariable::setPromptMode(-1);
189
190     if (ConfigVariable::getAnalyzerOptions() == 1)
191     {
192         //analysis::AnalysisVisitor analysis;
193         //pExp->accept(analysis);
194         //ast::DebugVisitor debugMe;
195         //pExp->accept(debugMe);
196     }
197
198     ast::SeqExp* pSeqExp = pExp->getAs<ast::SeqExp>();
199
200     // add execstr in list of macro called
201     // to manage line displayed when error occured.
202     ConfigVariable::macroFirstLine_begin(1);
203
204     ast::ConstVisitor* run = ConfigVariable::getDefaultVisitor();
205
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             delete run;
215         }
216         catch (const ast::RecursionException& /* re */)
217         {
218             //close opened scope during try
219             while (pCtx->getScopeLevel() > scope)
220             {
221                 pCtx->scope_end();
222             }
223
224             //decrease recursion to init value
225             while (ConfigVariable::getRecursionLevel() > level)
226             {
227                 ConfigVariable::where_end();
228                 ConfigVariable::decreaseRecursion();
229             }
230
231             //print msg about recursion limit and trigger an error
232             wchar_t sz[1024];
233             os_swprintf(sz, 1024, _W("Recursion limit reached (%d).\n").data(), ConfigVariable::getRecursionLimit());
234             throw ast::InternalError(sz);
235         }
236     }
237     catch (const ast::InternalError& ie)
238     {
239         if (bErrCatch == false)
240         {
241             delete pExp;
242             ConfigVariable::macroFirstLine_end();
243             ConfigVariable::setPromptMode(iPromptMode);
244             throw ie;
245         }
246
247         if (bMute == false)
248         {
249             scilabForcedWriteW(ie.GetErrorMessage().c_str());
250         }
251
252         ConfigVariable::resetWhereError();
253         iErr = ConfigVariable::getLastErrorNumber();
254     }
255
256     if (bErrCatch)
257     {
258         out.push_back(new types::Double(iErr));
259         //to lock last error information
260         ConfigVariable::setLastErrorCall();
261         // allow print
262         ConfigVariable::resetError();
263     }
264
265     ConfigVariable::macroFirstLine_end();
266     ConfigVariable::setPromptMode(iPromptMode);
267
268     delete pExp;
269     return types::Function::OK;
270 }
271 /*--------------------------------------------------------------------------*/