missing Lock on parseur added.
[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 "threadmanagement.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     if (in.size() < 1 || in.size() > 3)
59     {
60         Scierror(999, _("%s: Wrong number of input arguments: %d to %d expected.\n"), "execstr" , 1, 3);
61         return Function::Error;
62     }
63
64     //2nd parameter
65     if (in.size() > 1)
66     {
67         //errcatch
68         if (in[1]->isString() == false || in[1]->getAs<types::String>()->getSize() != 1)
69         {
70             Scierror(999, _("%s: Wrong type for input argument #%d: A string expected.\n"), "execstr", 2);
71             return Function::Error;
72         }
73
74         String* pS = in[1]->getAs<types::String>();
75         if (os_wcsicmp(pS->get(0), L"errcatch") == 0)
76         {
77             bErrCatch = true;
78         }
79         else
80         {
81             Scierror(999, _("%s: Wrong value for input argument #%d: 'errcatch' expected.\n"), "execstr", 2);
82             return Function::Error;
83         }
84
85         bMute = true;
86     }
87
88     //3rd parameter
89     if (in.size() == 3)
90     {
91         if (in[2]->isString() == false || in[2]->getAs<types::String>()->getSize() != 1)
92         {
93             Scierror(999, _("%s: Wrong type for input argument #%d: A string expected.\n"), "execstr", 3);
94             return Function::Error;
95         }
96
97         if (os_wcsicmp(in[2]->getAs<types::String>()->get(0), MUTE_FLAG) == 0)
98         {
99             bMute = true;
100         }
101         else if (os_wcsicmp(in[2]->getAs<types::String>()->get(0), NO_MUTE_FLAG) == 0)
102         {
103             bMute = false;
104         }
105         else
106         {
107             Scierror(999, _("%s: Wrong value for input argument #%d: '%s' or '%s' expected.\n"), "execstr", 3, MUTE_FLAG, NO_MUTE_FLAG);
108             return Function::Error;
109         }
110     }
111
112     //1st argument
113     if (in[0]->isDouble() && in[0]->getAs<Double>()->getSize() == 0)
114     {
115         // execstr([])
116         out.push_back(Double::Empty());
117         return Function::OK;
118     }
119
120     if (in[0]->isString() == false || (in[0]->getAs<types::String>()->getRows() != 1 && in[0]->getAs<types::String>()->getCols() != 1))
121     {
122         Scierror(999, _("%s: Wrong type for input argument #%d: Vector of strings expected.\n"), "execstr", 1);
123         return Function::Error;
124     }
125
126     String* pS = in[0]->getAs<types::String>();
127     int iTotalLen = pS->getSize(); //add \n after each string
128     for (int i = 0 ; i < pS->getSize() ; i++)
129     {
130         iTotalLen += (int)wcslen(pS->get(i));
131     }
132
133     pstCommand = (wchar_t*)MALLOC(sizeof(wchar_t) * (iTotalLen + 1));//+1 for null termination
134
135     for (int i = 0, iPos = 0 ; i < pS->getSize() ; i++)
136     {
137         wcscpy(pstCommand + iPos, pS->get(i));
138         iPos = (int)wcslen(pstCommand);
139         pstCommand[iPos++] = L'\n';
140         pstCommand[iPos] = 0;
141     }
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 Double(999));
151             //to lock last error information
152             ConfigVariable::setLastErrorCall();
153             ConfigVariable::setLastErrorMessage(parser.getErrorMessage());
154             ConfigVariable::setLastErrorNumber(999);
155             ThreadManagement::UnlockParser();
156             return Function::OK;
157         }
158         else
159         {
160             char* pst = wide_string_to_UTF8(parser.getErrorMessage());
161             Scierror(999, "%s", pst);
162             FREE(pst);
163             ThreadManagement::UnlockParser();
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     ThreadManagement::UnlockParser();
188
189     if (pExp == NULL)
190     {
191         return Function::Error;
192     }
193
194     //save current prompt mode
195     int iPromptMode = ConfigVariable::getPromptMode();
196     ConfigVariable::setPromptMode(-1);
197
198     if (ConfigVariable::getAnalyzerOptions() == 1)
199     {
200         //analysis::AnalysisVisitor analysis;
201         //pExp->accept(analysis);
202         //ast::DebugVisitor debugMe;
203         //pExp->accept(debugMe);
204     }
205
206     ast::SeqExp* pSeqExp = pExp->getAs<SeqExp>();
207
208     // add execstr in list of macro called
209     // to manage line displayed when error occured.
210     ConfigVariable::macroFirstLine_begin(1);
211
212     try
213     {
214         ExecVisitor execExps;
215         pSeqExp->accept(execExps);
216     }
217     catch (ast::ScilabMessage sm)
218     {
219         if (bErrCatch == false && bMute == false)
220         {
221             ConfigVariable::macroFirstLine_end();
222             ConfigVariable::setPromptMode(iPromptMode);
223             throw sm;
224         }
225
226         ConfigVariable::resetWhereError();
227         iErr = ConfigVariable::getLastErrorNumber();
228     }
229
230     if (bErrCatch)
231     {
232         out.push_back(new Double(iErr));
233         //to lock last error information
234         ConfigVariable::setLastErrorCall();
235         // allow print
236         ConfigVariable::resetError();
237     }
238
239     ConfigVariable::macroFirstLine_end();
240     ConfigVariable::setPromptMode(iPromptMode);
241
242     delete pExp;
243     return Function::OK;
244 }
245 /*--------------------------------------------------------------------------*/