2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2006 - INRIA - Antoine ELIAS
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
14 #include "functions_gw.hxx"
17 #include "funcmanager.hxx"
18 #include "context.hxx"
19 #include "execvisitor.hxx"
20 #include "mutevisitor.hxx"
21 #include "printvisitor.hxx"
22 #include "visitor_common.hxx"
23 #include "scilabWrite.hxx"
24 #include "scilabexception.hxx"
25 #include "configvariable.hxx"
26 #include "types_tools.hxx"
28 #include "threadmanagement.hxx"
30 #include "macrofile.hxx"
38 #include "os_string.h"
39 #include "expandPathVariable.h"
42 #include "localization.h"
43 #include "os_string.h"
51 void printLine(const std::string& _stPrompt, const std::string& _stLine, bool _bLF);
52 std::string printExp(std::ifstream& _File, Exp* _pExp, const std::string& _stPrompt, int* _piLine /* in/out */, int* _piCol /* in/out */, std::string& _stPreviousBuffer);
53 std::string getExpression(const std::string& _stFile, Exp* _pExp);
55 /*--------------------------------------------------------------------------*/
56 types::Function::ReturnValue sci_exec(types::typed_list &in, int _iRetCount, types::typed_list &out)
58 int promptMode = 0;//default value at startup, overthise 3 or verbose ";"
59 bool bPromptMode = false;
61 bool bErrCatch = false;
64 types::Macro* pMacro = NULL;
67 wchar_t* pwstFile = NULL;
71 std::ifstream* file = NULL;
73 if (ConfigVariable::getStartProcessing() == false)
75 if (ConfigVariable::getVerbose())
85 if (in.size() < 1 || in.size() > 3)
87 Scierror(999, _("%s: Wrong number of input arguments: %d to %d expected.\n"), "exec" , 1, 3);
88 return Function::Error;
91 // get mode and errcatch
95 if (in[1]->isString() && in[1]->getAs<types::String>()->isScalar())
98 String* pS = in[1]->getAs<types::String>();
99 if (os_wcsicmp(pS->get(0), L"errcatch") == 0)
105 Scierror(999, _("%s: Wrong value for input argument #%d: 'errcatch' expected.\n"), "exec", 2);
106 return Function::Error;
112 if (in[2]->isDouble() == false || in[2]->getAs<Double>()->isScalar() == false)
115 Scierror(999, _("%s: Wrong type for input argument #%d: A integer expected.\n"), "exec", 3);
116 return Function::Error;
119 promptMode = (int)in[2]->getAs<Double>()->getReal()[0];
123 else if (in[1]->isDouble() && in[1]->getAs<Double>()->isScalar())
127 Scierror(999, _("%s: Wrong value for input argument #%d: 'errcatch' expected.\n"), "exec", 2);
128 return Function::Error;
131 promptMode = (int)in[1]->getAs<Double>()->getReal()[0];
137 Scierror(999, _("%s: Wrong type for input argument #%d: A integer or string expected.\n"), "exec", 2);
138 return Function::Error;
142 if (in[0]->isString() && in[0]->getAs<types::String>()->isScalar())
144 //1st argument is a path, parse file and execute it
145 int iParsePathLen = 0;
146 String* pS = in[0]->getAs<types::String>();
148 pwstFile = expandPathVariableW(pS->get(0));
149 pstFile = wide_string_to_UTF8(pwstFile);
150 stFile = std::string(pstFile);
151 file = new std::ifstream(pstFile);
153 wchar_t* pwstTemp = (wchar_t*)MALLOC(sizeof(wchar_t) * (PATH_MAX * 2));
154 get_full_pathW(pwstTemp, (const wchar_t*)pwstFile, PATH_MAX * 2);
156 /*fake call to mopen to show file within file()*/
157 if (mopen(pwstTemp, L"r", 0, &iID) != MOPEN_NO_ERROR)
160 Scierror(999, _("%s: Cannot open file %s.\n"), "exec", pstFile);
161 return Function::Error;
164 ThreadManagement::LockParser();
165 parser.parseFile(pwstTemp, L"exec");
167 if (parser.getExitStatus() != Parser::Succeded)
171 out.push_back(new Double(999));
172 //to lock last error information
173 ConfigVariable::setLastErrorCall();
174 ConfigVariable::setLastErrorMessage(parser.getErrorMessage());
175 ConfigVariable::setLastErrorNumber(999);
176 delete parser.getTree();
178 ThreadManagement::UnlockParser();
182 char* pst = wide_string_to_UTF8(parser.getErrorMessage());
183 Scierror(999, "%s", pst);
186 delete parser.getTree();
188 ThreadManagement::UnlockParser();
189 return Function::Error;
192 if (ConfigVariable::getSerialize())
194 ast::Exp* temp = parser.getTree();
195 if (ConfigVariable::getTimed())
197 pExp = callTyper(temp, L"exec");
201 pExp = callTyper(temp);
208 pExp = parser.getTree();
211 ThreadManagement::UnlockParser();
212 // update where to set the name of the executed file.
213 ConfigVariable::setFileNameToLastWhere(pwstFile);
215 ConfigVariable::setExecutedFileID(iID);
217 else if (in[0]->isMacro() || in[0]->isMacroFile())
220 optional_list optional;
222 ast::ExecVisitor execFunc;
224 if (in[0]->isMacroFile())
226 //1st argument is a macro name, parse and execute it in the current environnement
227 if (in[0]->getAs<MacroFile>()->parse() == false)
229 char* pstMacro = wide_string_to_UTF8(in[0]->getAs<MacroFile>()->getName().c_str());
230 Scierror(999, _("%s: Unable to parse macro '%s'"), "exec", pstMacro);
232 return Function::Error;
234 pMacro = in[0]->getAs<MacroFile>()->getMacro();
236 else //1st argument is a macro name, execute it in the current environnement
238 pMacro = in[0]->getAs<Macro>();
241 // unable for macro with varargin or varargout
242 auto inputs = pMacro->getInputs();
243 auto outputs = pMacro->getOutputs();
244 if ((inputs->size() != 0 && inputs->back()->getSymbol().getName() == L"varargin") ||
245 outputs->size() != 0 && outputs->back()->getSymbol().getName() == L"varargout")
247 Scierror(999, _("%s: Wrong type for input argument #%d: A macro without varargin and varargout expected.\n"), "exec", 1);
248 return Function::Error;
251 pExp = pMacro->getBody();
253 // update where to set the name of the executed macro instead of "exec"
254 ConfigVariable::WhereEntry lastWhere = ConfigVariable::getWhere().back();
255 int iLine = lastWhere.m_line;
256 int iAbsLine = lastWhere.m_absolute_line;
257 ConfigVariable::where_end();
258 ConfigVariable::where_begin(iLine, iAbsLine, pMacro);
262 Scierror(999, _("%s: Wrong type for input argument #%d: A string expected.\n"), "exec", 1);
263 return Function::Error;
268 //store the line number where is stored this macro in file.
269 ConfigVariable::macroFirstLine_begin(pMacro->getFirstLine());
272 //save current prompt mode
273 int oldVal = ConfigVariable::getPromptMode();
274 ConfigVariable::setPromptMode(promptMode);
276 // if not exp displaying, just execute the seqexp
277 if (file == NULL || promptMode == 0 || promptMode == 2)
279 ast::SeqExp* pSeqExp = pExp->getAs<SeqExp>();
283 ExecVisitor execExps;
284 pSeqExp->accept(execExps);
286 catch (ast::ScilabMessage sm)
288 if (bErrCatch == false)
290 ConfigVariable::setPromptMode(oldVal);
291 ConfigVariable::setExecutedFileID(0);
295 ConfigVariable::resetWhereError();
296 iErr = ConfigVariable::getLastErrorNumber();
301 ast::exps_t& LExp = pExp->getAs<SeqExp>()->getExps();
305 GetCurrentPrompt(pstPrompt);
306 std::string stPrompt(pstPrompt);
309 int iCurrentLine = -1; //no data in str
310 int iCurrentCol = 0; //no data in str
312 for (ast::exps_t::iterator j = LExp.begin(), itEnd = LExp.end() ; j != itEnd; ++j)
315 ast::exps_t::iterator k = j;
316 int iLastLine = (*j)->getLocation().last_line;
319 str = printExp(*file, *k, stPrompt, &iCurrentLine, &iCurrentCol, str);
320 iLastLine = (*k)->getLocation().last_line;
323 while (k != LExp.end() && (*k)->getLocation().first_line == iLastLine);
325 // In case where the line ends by spaces, iCurrentCol is not reset
326 // by printExp because we don't know if that's the end of the expression
327 // before go out of the loop. So we have to reset column count
328 // and print a new line before manage the next line.
329 if (iCurrentCol != 0)
332 printLine("", "", true);
335 // create a seqexp with printed exp
336 ast::exps_t* someExps = new ast::exps_t();
337 someExps->assign(j, k);
339 SeqExp seqExp(Location((*j)->getLocation().first_line, (*k)->getLocation().last_line,
340 (*j)->getLocation().first_column, (*k)->getLocation().last_column),
347 // execute printed exp
348 ExecVisitor execExps;
349 seqExp.accept(execExps);
351 catch (ast::ScilabMessage sm)
353 ConfigVariable::fillWhereError(sm.GetErrorLocation().first_line);
367 // reset last first line of macro called
368 ConfigVariable::macroFirstLine_end();
371 if (bErrCatch == false)
373 ConfigVariable::setPromptMode(oldVal);
374 ConfigVariable::setExecutedFileID(0);
376 // avoid double delete on exps when "seqExp" is destryed and "LExp" too
377 ast::exps_t& protectExp = seqExp.getExps();
378 for (int i = 0; i < protectExp.size(); ++i)
380 protectExp[i] = NULL;
386 ConfigVariable::resetWhereError();
387 iErr = ConfigVariable::getLastErrorNumber();
389 catch (ast::ScilabError& se)
391 ConfigVariable::setExecutedFileID(0);
392 ConfigVariable::fillWhereError(se.GetErrorLocation().first_line);
393 if (ConfigVariable::getLastErrorNumber() == 0)
395 ConfigVariable::setLastErrorMessage(se.GetErrorMessage());
396 ConfigVariable::setLastErrorNumber(se.GetErrorNumber());
397 ConfigVariable::setLastErrorLine(se.GetErrorLocation().first_line);
398 ConfigVariable::setLastErrorFunction(wstring(L""));
402 iErr = ConfigVariable::getLastErrorNumber();
403 if (bErrCatch == false)
415 //restore previous prompt mode
416 ConfigVariable::setPromptMode(oldVal);
418 // avoid double delete on exps when "seqExp" is destryed and "LExp" too
419 ast::exps_t& protectExp = seqExp.getExps();
420 for (int i = 0; i < protectExp.size(); ++i)
422 protectExp[i] = NULL;
430 // reset last first line of macro called
431 ConfigVariable::macroFirstLine_end();
434 ConfigVariable::resetWhereError();
438 ConfigVariable::setExecutedFileID(0);
440 // avoid double delete on exps when "seqExp" is destryed and "LExp" too
441 ast::exps_t& protectExp = seqExp.getExps();
442 for (int i = 0; i < protectExp.size(); ++i)
444 protectExp[i] = NULL;
449 //restore previous prompt mode
450 ConfigVariable::setPromptMode(oldVal);
453 out.push_back(new Double(iErr));
454 //to lock last error information
455 ConfigVariable::setLastErrorCall();
471 std::string getExpression(const std::string& _stFile, Exp* _pExp)
474 std::string stBuffer;
476 Location loc = _pExp->getLocation();
477 std::ifstream file(_stFile.c_str());
479 //bypass previous lines
480 for (int i = 0 ; i < loc.first_line; i++)
482 std::getline(file, stBuffer);
485 if (loc.first_line == loc.last_line)
487 int iStart = loc.first_column - 1;
488 int iEnd = loc.last_column - 1;
489 int iLen = iEnd - iStart;
490 out += string(stBuffer.c_str() + iStart, iLen);
496 //first line, entire or not
497 out += string(stBuffer.c_str() + loc.first_column - 1);
500 //print other full lines
501 for (int i = loc.first_line; i < (loc.last_line - 1) ; i++)
503 std::getline(file, stBuffer);
509 //last line, entire or not
510 getline(file, stBuffer);
511 out += string(stBuffer.c_str(), loc.last_column - 1);
517 std::string printExp(std::ifstream& _File, Exp* _pExp, const std::string& _stPrompt, int* _piLine /* in/out */, int* _piCol /* in/out */, std::string& _stPreviousBuffer)
519 //case 1, exp is on 1 line and take the entire line
521 //case 2, exp is multiline
523 //case 3, exp is part of a line.
524 //ex : 3 exp on the same line a = 1; b = 2; c = 3;
526 //case 4, exp is multiline but start and/or finish in the middle of a line
528 //a = 10;for i = 1 : a
532 Location loc = _pExp->getLocation();
534 //positionning file curser at loc.first_line
536 //strange case, current position is after the wanted position
537 if (*_piLine > loc.first_line)
539 //reset line counter and restart reading at the start of the file.
541 _File.seekg( 0, ios_base::beg );
544 //bypass previous lines
545 for (int i = *_piLine ; i < loc.first_line - 1; i++)
549 if ((*_piLine) != (loc.first_line - 1))
551 //empty line but not sequential lines
552 printLine("", "", true);
554 std::getline(_File, _stPreviousBuffer);
558 if (loc.first_line == loc.last_line)
561 int iStart = loc.first_column - 1;
562 int iEnd = loc.last_column - 1;
563 int iLen = iEnd - iStart;
564 std::string strLastLine(_stPreviousBuffer.c_str() + iStart, iLen);
566 int iLineLen = (int)_stPreviousBuffer.size();
567 //printLine(_pstPrompt, strLastLine, true, false);
569 if (iStart == 0 && iExpLen == iLineLen)
574 //blank char at the end of previous line
575 printLine("", "", true);
577 printLine(_stPrompt, strLastLine, true);
587 //blank char at the end of previous line
588 printLine("", "", true);
590 printLine(_stPrompt, strLastLine, false);
591 *_piCol = loc.last_column;
597 printLine(_stPrompt, "", false);
601 if (*_piCol < loc.first_column)
603 //pickup separator between expressionsfrom file and add to output
604 int iSize = loc.first_column - *_piCol;
605 std::string stTemp(_stPreviousBuffer.c_str() + (*_piCol - 1), iSize);
606 printLine("", stTemp, false);
607 *_piCol = loc.first_column;
610 if (iEnd == iLineLen)
612 printLine("", strLastLine, true);
617 printLine("", strLastLine, false);
618 *_piCol = loc.last_column;
627 if (loc.first_column == 1)
631 //blank char at the end of previous line
632 printLine("", "", true);
634 printLine(_stPrompt, _stPreviousBuffer.c_str() + (loc.first_column - 1), false);
638 if (*_piCol < loc.first_column)
640 //pickup separator between expressionsfrom file and add to output
641 printLine(_stPrompt, _stPreviousBuffer.c_str(), false);
642 *_piCol = loc.first_column;
646 //print other full lines
647 for (int i = loc.first_line; i < (loc.last_line - 1) ; i++)
650 std::getline(_File, _stPreviousBuffer);
651 // dont print empty line of function body
652 if (_stPreviousBuffer.size() != 0)
654 printLine(_stPrompt, _stPreviousBuffer.c_str(), false);
659 std::getline(_File, _stPreviousBuffer);
662 int iSize = loc.last_column - 1;
663 std::string stLastLine(_stPreviousBuffer.c_str(), iSize);
664 int iLineLen = (int)_stPreviousBuffer.size();
665 if (iLineLen == iSize)
667 printLine(_stPrompt, stLastLine, true);
672 printLine(_stPrompt, stLastLine, false);
673 *_piCol = loc.last_column;
677 return _stPreviousBuffer;
680 void printLine(const std::string& _stPrompt, const std::string& _stLine, bool _bLF)
684 if (_stPrompt.size() != 0)
686 st = "\n" + _stPrompt;
690 if (_bLF && ConfigVariable::isEmptyLineShow())
695 scilabWrite(st.c_str());
697 /*--------------------------------------------------------------------------*/