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