exec and ecestr fixed about parsing error.
[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 "debugvisitor.hxx"
18 #include "execvisitor.hxx"
19 #include "mutevisitor.hxx"
20 #include "printvisitor.hxx"
21 #include "visitor_common.hxx"
22 #include "scilabWrite.hxx"
23 #include "scilabexception.hxx"
24 #include "configvariable.hxx"
25 #include "context.hxx"
26 #include "runner.hxx"
27 #include "threadmanagement.hxx"
28
29 #include <iostream>
30 #include <fstream>
31 #include <string>
32
33 extern "C"
34 {
35 #include "sci_malloc.h"
36 #include "os_string.h"
37 #include "Scierror.h"
38 #include "sciprint.h"
39 #include "localization.h"
40 #include "os_string.h"
41 }
42
43 #define MUTE_FLAG       L"n"
44 #define NO_MUTE_FLAG    L"m"
45
46 using namespace std;
47 using namespace types;
48 using namespace ast;
49 /*--------------------------------------------------------------------------*/
50 Function::ReturnValue sci_execstr(types::typed_list &in, int _iRetCount, types::typed_list &out)
51 {
52     int iErr            = 0;
53     bool bErrCatch              = false;
54     bool bMute          = false;
55     wchar_t* pstMsg     = NULL;
56     Exp* pExp           = NULL;
57     wchar_t *pstCommand = NULL;
58     Parser parser;
59
60     int iOldSilentError = ConfigVariable::getSilentError();
61     if (in.size() < 1 || in.size() > 3)
62     {
63         Scierror(999, _("%s: Wrong number of input arguments: %d to %d expected.\n"), "execstr" , 1, 3);
64         return Function::Error;
65     }
66
67     //2nd parameter
68     if (in.size() > 1)
69     {
70         //errcatch
71         if (in[1]->isString() == false || in[1]->getAs<types::String>()->getSize() != 1)
72         {
73             Scierror(999, _("%s: Wrong type for input argument #%d: A string expected.\n"), "execstr", 2);
74             return Function::Error;
75         }
76
77         String* pS = in[1]->getAs<types::String>();
78         if (os_wcsicmp(pS->get(0), L"errcatch") == 0)
79         {
80             bErrCatch = true;
81         }
82         else
83         {
84             Scierror(999, _("%s: Wrong value for input argument #%d: 'errcatch' expected.\n"), "execstr", 2);
85             return Function::Error;
86         }
87
88         bMute = true;
89     }
90
91     //3rd parameter
92     if (in.size() == 3)
93     {
94         if (in[2]->isString() == false || in[2]->getAs<types::String>()->getSize() != 1)
95         {
96             Scierror(999, _("%s: Wrong type for input argument #%d: A string expected.\n"), "execstr", 3);
97             return Function::Error;
98         }
99
100         if (os_wcsicmp(in[2]->getAs<types::String>()->get(0), MUTE_FLAG) == 0)
101         {
102             bMute = true;
103         }
104         else if (os_wcsicmp(in[2]->getAs<types::String>()->get(0), NO_MUTE_FLAG) == 0)
105         {
106             bMute = false;
107         }
108         else
109         {
110             Scierror(999, _("%s: Wrong value for input argument #%d: '%s' or '%s' expected.\n"), "execstr", 3, MUTE_FLAG, NO_MUTE_FLAG);
111             return Function::Error;
112         }
113     }
114
115     //1st argument
116     if (in[0]->isDouble() && in[0]->getAs<Double>()->getSize() == 0)
117     {
118         // execstr([])
119         out.push_back(Double::Empty());
120         return Function::OK;
121     }
122
123     if (in[0]->isString() == false || (in[0]->getAs<types::String>()->getRows() != 1 && in[0]->getAs<types::String>()->getCols() != 1))
124     {
125         Scierror(999, _("%s: Wrong type for input argument #%d: Vector of strings expected.\n"), "execstr", 1);
126         return Function::Error;
127     }
128
129     String* pS = in[0]->getAs<types::String>();
130     int iTotalLen = pS->getSize(); //add \n after each string
131     for (int i = 0 ; i < pS->getSize() ; i++)
132     {
133         iTotalLen += (int)wcslen(pS->get(i));
134     }
135
136     pstCommand = (wchar_t*)MALLOC(sizeof(wchar_t) * (iTotalLen + 1));//+1 for null termination
137
138     for (int i = 0, iPos = 0 ; i < pS->getSize() ; i++)
139     {
140         wcscpy(pstCommand + iPos, pS->get(i));
141         iPos = (int)wcslen(pstCommand);
142         pstCommand[iPos++] = L'\n';
143         pstCommand[iPos] = 0;
144     }
145
146     parser.parse(pstCommand);
147     FREE(pstCommand);
148     if (parser.getExitStatus() !=  Parser::Succeded)
149     {
150         if (bErrCatch)
151         {
152             out.push_back(new Double(999));
153             //to lock last error information
154             ConfigVariable::setLastErrorCall();
155             ConfigVariable::setLastErrorMessage(parser.getErrorMessage());
156             ConfigVariable::setLastErrorNumber(999);
157             return Function::OK;
158         }
159         else
160         {
161             char* pst = wide_string_to_UTF8(parser.getErrorMessage());
162             Scierror(999, "%s", pst);
163             FREE(pst);
164             return Function::Error;
165         }
166     }
167
168     if (ConfigVariable::getSerialize())
169     {
170         ast::Exp* temp = parser.getTree();
171         if (ConfigVariable::getTimed())
172         {
173             pExp = callTyper(temp, L"execstr");
174         }
175         else
176         {
177             pExp = callTyper(temp);
178         }
179
180         delete temp;
181     }
182     else
183     {
184         pExp = parser.getTree();
185     }
186
187     if (pExp == NULL)
188     {
189         return Function::Error;
190     }
191
192     //save current prompt mode
193     int oldVal = ConfigVariable::getPromptMode();
194     ConfigVariable::setPromptMode(-1);
195
196     if (bErrCatch)
197     {
198         ConfigVariable::setSilentError(1);
199     }
200
201     if (ConfigVariable::getAnalyzerOptions() == 1)
202     {
203         analysis::AnalysisVisitor analysis;
204         pExp->accept(analysis);
205         //ast::DebugVisitor debugMe;
206         //pExp->accept(debugMe);
207     }
208
209     ast::exps_t LExp = pExp->getAs<SeqExp>()->getExps();
210
211     types::ThreadId* pThreadMe = ConfigVariable::getThread(__GetCurrentThreadKey());
212
213     for (ast::exps_t::iterator j = LExp.begin(), itEnd = LExp.end(); j != itEnd; ++j)
214     {
215         try
216         {
217             if (pThreadMe && pThreadMe->getInterrupt())
218             {
219                 ThreadManagement::SendAstPendingSignal();
220                 pThreadMe->suspend();
221             }
222
223             //excecute script
224             ExecVisitor execMe;
225             (*j)->accept(execMe);
226
227             //to manage call without ()
228             if (execMe.getResult() != NULL && execMe.getResult()->isCallable())
229             {
230                 Callable *pCall = execMe.getResult()->getAs<Callable>();
231                 types::typed_list out;
232                 types::typed_list in;
233                 types::optional_list opt;
234
235                 try
236                 {
237                     ExecVisitor execCall;
238                     Function::ReturnValue Ret = pCall->call(in, opt, 1, out, &execCall);
239
240                     if (Ret == Callable::OK)
241                     {
242                         if (out.size() == 0)
243                         {
244                             execMe.setResult(NULL);
245                         }
246                         else if (out.size() == 1)
247                         {
248                             out[0]->DecreaseRef();
249                             execMe.setResult(out[0]);
250                         }
251                         else
252                         {
253                             for (int i = 0; i < static_cast<int>(out.size()); i++)
254                             {
255                                 out[i]->DecreaseRef();
256                                 execMe.setResult(i, out[i]);
257                             }
258                         }
259                     }
260                     else if (Ret == Callable::Error)
261                     {
262                         ConfigVariable::setSilentError(iOldSilentError);
263                         if (ConfigVariable::getLastErrorFunction() == L"")
264                         {
265                             ConfigVariable::setLastErrorFunction(pCall->getName());
266                         }
267
268                         if (pCall->isMacro() || pCall->isMacroFile())
269                         {
270                             wchar_t szError[bsiz];
271                             os_swprintf(szError, bsiz, _W("at line % 5d of function %ls called by :\n").c_str(), (*j)->getLocation().first_line, pCall->getName().c_str());
272                             throw ast::ScilabMessage(szError);
273                         }
274                         else
275                         {
276                             throw ast::ScilabMessage();
277                         }
278                     }
279                 }
280                 catch (ScilabMessage sm)
281                 {
282                     ConfigVariable::setSilentError(iOldSilentError);
283                     wostringstream os;
284                     PrintVisitor printMe(os);
285                     (*j)->accept(printMe);
286                     os << std::endl << std::endl;
287                     if (ConfigVariable::getLastErrorFunction() == L"")
288                     {
289                         ConfigVariable::setLastErrorFunction(pCall->getName());
290                     }
291
292                     if (pCall->isMacro() || pCall->isMacroFile())
293                     {
294                         wstring szAllError;
295                         wchar_t szError[bsiz];
296                         os_swprintf(szError, bsiz, _W("at line % 5d of function %ls called by :\n").c_str(), sm.GetErrorLocation().first_line, pCall->getName().c_str());
297                         szAllError = szError + os.str();
298                         os_swprintf(szError, bsiz, _W("in  execstr instruction    called by :\n").c_str());
299                         szAllError += szError;
300                         throw ast::ScilabMessage(szAllError);
301                     }
302                     else
303                     {
304                         sm.SetErrorMessage(sm.GetErrorMessage() + os.str());
305                         throw sm;
306                     }
307                 }
308             }
309
310             //update ans variable.
311             if (execMe.getResult() != NULL && execMe.getResult()->isDeletable())
312             {
313                 InternalType* pITAns = execMe.getResult();
314                 symbol::Context::getInstance()->put(symbol::Symbol(L"ans"), pITAns);
315                 if ((*j)->isVerbose() && bErrCatch == false)
316                 {
317                     std::wostringstream ostr;
318                     ostr << L" ans  =" << std::endl;
319                     ostr << std::endl;
320                     pITAns->toString(ostr);
321                     ostr << std::endl;
322                     scilabWriteW(ostr.str().c_str());
323                 }
324             }
325
326             //if( !checkPrompt(iMode, EXEC_MODE_MUTE) &&
327             //             bErrCatch == false)
328             //{
329             //  scilabWriteW(L"\n");
330             //}
331         }
332         catch (ScilabMessage sm)
333         {
334             ConfigVariable::setSilentError(iOldSilentError);
335             if (bErrCatch == false && bMute == false)
336             {
337                 scilabErrorW(sm.GetErrorMessage().c_str());
338
339                 CallExp* pCall = dynamic_cast<CallExp*>(*j);
340                 if (pCall != NULL)
341                 {
342                     //to print call expression only of it is a macro
343                     ExecVisitor execFunc;
344                     pCall->getName().accept(execFunc);
345
346                     if (execFunc.getResult() != NULL &&
347                             (execFunc.getResult()->isMacro() || execFunc.getResult()->isMacroFile()))
348                     {
349                         wostringstream os;
350
351                         //add function failed
352                         PrintVisitor printMe(os);
353                         pCall->accept(printMe);
354                         os << std::endl;
355
356                         //add info on file failed
357                         wchar_t szError[bsiz];
358                         os_swprintf(szError, bsiz, _W("at line % 5d of exec file called by :\n").c_str(), (*j)->getLocation().first_line);
359                         os << szError;
360
361                         if (ConfigVariable::getLastErrorFunction() == L"")
362                         {
363                             ConfigVariable::setLastErrorFunction(execFunc.getResult()->getAs<Callable>()->getName());
364                         }
365
366                         //restore previous prompt mode
367                         ConfigVariable::setPromptMode(oldVal);
368                         throw ast::ScilabMessage(os.str(), 0, (*j)->getLocation());
369                     }
370                 }
371                 throw ast::ScilabMessage((*j)->getLocation());
372             }
373             else
374             {
375                 iErr = ConfigVariable::getLastErrorNumber();
376                 break;
377             }
378         }
379         catch (ast::ScilabError se)
380         {
381             ConfigVariable::setSilentError(iOldSilentError);
382             // check on error number because error message can be empty.
383             if (ConfigVariable::getLastErrorNumber() == 0)
384             {
385                 ConfigVariable::setLastErrorMessage(se.GetErrorMessage());
386                 ConfigVariable::setLastErrorNumber(se.GetErrorNumber());
387                 ConfigVariable::setLastErrorLine(se.GetErrorLocation().first_line);
388                 ConfigVariable::setLastErrorFunction(wstring(L""));
389             }
390
391             //store message
392             iErr = ConfigVariable::getLastErrorNumber();
393             if (bErrCatch == false)
394             {
395                 //in case of error, change mode to 2 ( prompt )
396                 ConfigVariable::setPromptMode(2);
397                 //write error
398                 scilabErrorW(se.GetErrorMessage().c_str());
399
400                 //write positino
401                 // sciprint(_("in  execstr instruction    called by :\n"));
402                 //restore previous prompt mode
403                 ConfigVariable::setPromptMode(oldVal);
404                 //throw ast::ScilabMessage(szError, 1, (*j)->getLocation());
405                 //print already done, so just foward exception but with message
406                 //throw ast::ScilabError();
407                 return Function::Error;
408             }
409             break;
410         }
411     }
412
413     //restore previous prompt mode and silent mode
414     ConfigVariable::setPromptMode(oldVal);
415     ConfigVariable::setSilentError(iOldSilentError);
416
417     if (bErrCatch)
418     {
419         out.push_back(new Double(iErr));
420         //to lock last error information
421         ConfigVariable::setLastErrorCall();
422         // allow print
423         ConfigVariable::resetError();
424     }
425
426     delete pExp;
427     return Function::OK;
428 }
429 /*--------------------------------------------------------------------------*/