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 parser.parseFile(pwstTemp, L"exec");
166 if (parser.getExitStatus() != Parser::Succeded)
170 out.push_back(new Double(999));
171 //to lock last error information
172 ConfigVariable::setLastErrorCall();
173 ConfigVariable::setLastErrorMessage(parser.getErrorMessage());
174 ConfigVariable::setLastErrorNumber(999);
175 delete parser.getTree();
180 char* pst = wide_string_to_UTF8(parser.getErrorMessage());
181 Scierror(999, "%s", pst);
184 delete parser.getTree();
186 return Function::Error;
189 if (ConfigVariable::getSerialize())
191 ast::Exp* temp = parser.getTree();
192 if (ConfigVariable::getTimed())
194 pExp = callTyper(temp, L"exec");
198 pExp = callTyper(temp);
205 pExp = parser.getTree();
208 // update where to set the name of the executed file.
209 ConfigVariable::setFileNameToLastWhere(pwstFile);
211 ConfigVariable::setExecutedFileID(iID);
213 else if (in[0]->isMacro() || in[0]->isMacroFile())
216 optional_list optional;
218 ast::ExecVisitor execFunc;
220 if (in[0]->isMacroFile())
222 //1st argument is a macro name, parse and execute it in the current environnement
223 if (in[0]->getAs<MacroFile>()->parse() == false)
225 char* pstMacro = wide_string_to_UTF8(in[0]->getAs<MacroFile>()->getName().c_str());
226 Scierror(999, _("%s: Unable to parse macro '%s'"), "exec", pstMacro);
228 return Function::Error;
230 pMacro = in[0]->getAs<MacroFile>()->getMacro();
232 else //1st argument is a macro name, execute it in the current environnement
234 pMacro = in[0]->getAs<Macro>();
237 // unable for macro with varargin or varargout
238 auto inputs = pMacro->getInputs();
239 auto outputs = pMacro->getOutputs();
240 if ((inputs->size() != 0 && inputs->back()->getSymbol().getName() == L"varargin") ||
241 outputs->size() != 0 && outputs->back()->getSymbol().getName() == L"varargout")
243 Scierror(999, _("%s: Wrong type for input argument #%d: A macro without varargin and varargout expected.\n"), "exec", 1);
244 return Function::Error;
247 pExp = pMacro->getBody();
249 // update where to set the name of the executed macro instead of "exec"
250 ConfigVariable::WhereEntry lastWhere = ConfigVariable::getWhere().back();
251 int iLine = lastWhere.m_line;
252 int iAbsLine = lastWhere.m_absolute_line;
253 ConfigVariable::where_end();
254 ConfigVariable::where_begin(iLine, iAbsLine, pMacro);
258 Scierror(999, _("%s: Wrong type for input argument #%d: A string expected.\n"), "exec", 1);
259 return Function::Error;
264 //store the line number where is stored this macro in file.
265 ConfigVariable::macroFirstLine_begin(pMacro->getFirstLine());
268 //save current prompt mode
269 int oldVal = ConfigVariable::getPromptMode();
270 ConfigVariable::setPromptMode(promptMode);
272 // if not exp displaying, just execute the seqexp
273 if (file == NULL || promptMode == 0 || promptMode == 2)
275 ast::SeqExp* pSeqExp = pExp->getAs<SeqExp>();
279 ExecVisitor execExps;
280 pSeqExp->accept(execExps);
282 catch (ast::ScilabMessage sm)
284 if (bErrCatch == false)
286 ConfigVariable::setPromptMode(oldVal);
287 ConfigVariable::setExecutedFileID(0);
291 ConfigVariable::resetWhereError();
292 iErr = ConfigVariable::getLastErrorNumber();
297 ast::exps_t& LExp = pExp->getAs<SeqExp>()->getExps();
301 GetCurrentPrompt(pstPrompt);
302 std::string stPrompt(pstPrompt);
305 int iCurrentLine = -1; //no data in str
306 int iCurrentCol = 0; //no data in str
308 for (ast::exps_t::iterator j = LExp.begin(), itEnd = LExp.end() ; j != itEnd; ++j)
311 ast::exps_t::iterator k = j;
312 int iLastLine = (*j)->getLocation().last_line;
315 str = printExp(*file, *k, stPrompt, &iCurrentLine, &iCurrentCol, str);
316 iLastLine = (*k)->getLocation().last_line;
319 while (k != LExp.end() && (*k)->getLocation().first_line == iLastLine);
321 // In case where the line ends by spaces, iCurrentCol is not reset
322 // by printExp because we don't know if that's the end of the expression
323 // before go out of the loop. So we have to reset column count
324 // and print a new line before manage the next line.
325 if (iCurrentCol != 0)
328 printLine("", "", true);
331 // create a seqexp with printed exp
332 ast::exps_t* someExps = new ast::exps_t();
333 someExps->assign(j, k);
335 SeqExp seqExp(Location((*j)->getLocation().first_line, (*k)->getLocation().last_line,
336 (*j)->getLocation().first_column, (*k)->getLocation().last_column),
343 // execute printed exp
344 ExecVisitor execExps;
345 seqExp.accept(execExps);
347 catch (ast::ScilabMessage sm)
349 ConfigVariable::fillWhereError(sm.GetErrorLocation().first_line);
363 // reset last first line of macro called
364 ConfigVariable::macroFirstLine_end();
367 if (bErrCatch == false)
369 ConfigVariable::setPromptMode(oldVal);
370 ConfigVariable::setExecutedFileID(0);
372 // avoid double delete on exps when "seqExp" is destryed and "LExp" too
373 ast::exps_t& protectExp = seqExp.getExps();
374 for (int i = 0; i < protectExp.size(); ++i)
376 protectExp[i] = NULL;
382 ConfigVariable::resetWhereError();
383 iErr = ConfigVariable::getLastErrorNumber();
385 catch (ast::ScilabError& se)
387 ConfigVariable::setExecutedFileID(0);
388 ConfigVariable::fillWhereError(se.GetErrorLocation().first_line);
389 if (ConfigVariable::getLastErrorNumber() == 0)
391 ConfigVariable::setLastErrorMessage(se.GetErrorMessage());
392 ConfigVariable::setLastErrorNumber(se.GetErrorNumber());
393 ConfigVariable::setLastErrorLine(se.GetErrorLocation().first_line);
394 ConfigVariable::setLastErrorFunction(wstring(L""));
398 iErr = ConfigVariable::getLastErrorNumber();
399 if (bErrCatch == false)
411 //restore previous prompt mode
412 ConfigVariable::setPromptMode(oldVal);
414 // avoid double delete on exps when "seqExp" is destryed and "LExp" too
415 ast::exps_t& protectExp = seqExp.getExps();
416 for (int i = 0; i < protectExp.size(); ++i)
418 protectExp[i] = NULL;
426 // reset last first line of macro called
427 ConfigVariable::macroFirstLine_end();
430 ConfigVariable::resetWhereError();
434 ConfigVariable::setExecutedFileID(0);
436 // avoid double delete on exps when "seqExp" is destryed and "LExp" too
437 ast::exps_t& protectExp = seqExp.getExps();
438 for (int i = 0; i < protectExp.size(); ++i)
440 protectExp[i] = NULL;
445 //restore previous prompt mode
446 ConfigVariable::setPromptMode(oldVal);
449 out.push_back(new Double(iErr));
450 //to lock last error information
451 ConfigVariable::setLastErrorCall();
467 std::string getExpression(const std::string& _stFile, Exp* _pExp)
470 std::string stBuffer;
472 Location loc = _pExp->getLocation();
473 std::ifstream file(_stFile.c_str());
475 //bypass previous lines
476 for (int i = 0 ; i < loc.first_line; i++)
478 std::getline(file, stBuffer);
481 if (loc.first_line == loc.last_line)
483 int iStart = loc.first_column - 1;
484 int iEnd = loc.last_column - 1;
485 int iLen = iEnd - iStart;
486 out += string(stBuffer.c_str() + iStart, iLen);
492 //first line, entire or not
493 out += string(stBuffer.c_str() + loc.first_column - 1);
496 //print other full lines
497 for (int i = loc.first_line; i < (loc.last_line - 1) ; i++)
499 std::getline(file, stBuffer);
505 //last line, entire or not
506 getline(file, stBuffer);
507 out += string(stBuffer.c_str(), loc.last_column - 1);
513 std::string printExp(std::ifstream& _File, Exp* _pExp, const std::string& _stPrompt, int* _piLine /* in/out */, int* _piCol /* in/out */, std::string& _stPreviousBuffer)
515 //case 1, exp is on 1 line and take the entire line
517 //case 2, exp is multiline
519 //case 3, exp is part of a line.
520 //ex : 3 exp on the same line a = 1; b = 2; c = 3;
522 //case 4, exp is multiline but start and/or finish in the middle of a line
524 //a = 10;for i = 1 : a
528 Location loc = _pExp->getLocation();
530 //positionning file curser at loc.first_line
532 //strange case, current position is after the wanted position
533 if (*_piLine > loc.first_line)
535 //reset line counter and restart reading at the start of the file.
537 _File.seekg( 0, ios_base::beg );
540 //bypass previous lines
541 for (int i = *_piLine ; i < loc.first_line - 1; i++)
545 if ((*_piLine) != (loc.first_line - 1))
547 //empty line but not sequential lines
548 printLine("", "", true);
550 std::getline(_File, _stPreviousBuffer);
554 if (loc.first_line == loc.last_line)
557 int iStart = loc.first_column - 1;
558 int iEnd = loc.last_column - 1;
559 int iLen = iEnd - iStart;
560 std::string strLastLine(_stPreviousBuffer.c_str() + iStart, iLen);
562 int iLineLen = (int)_stPreviousBuffer.size();
563 //printLine(_pstPrompt, strLastLine, true, false);
565 if (iStart == 0 && iExpLen == iLineLen)
570 //blank char at the end of previous line
571 printLine("", "", true);
573 printLine(_stPrompt, strLastLine, true);
583 //blank char at the end of previous line
584 printLine("", "", true);
586 printLine(_stPrompt, strLastLine, false);
587 *_piCol = loc.last_column;
593 printLine(_stPrompt, "", false);
597 if (*_piCol < loc.first_column)
599 //pickup separator between expressionsfrom file and add to output
600 int iSize = loc.first_column - *_piCol;
601 std::string stTemp(_stPreviousBuffer.c_str() + (*_piCol - 1), iSize);
602 printLine("", stTemp, false);
603 *_piCol = loc.first_column;
606 if (iEnd == iLineLen)
608 printLine("", strLastLine, true);
613 printLine("", strLastLine, false);
614 *_piCol = loc.last_column;
623 if (loc.first_column == 1)
627 //blank char at the end of previous line
628 printLine("", "", true);
630 printLine(_stPrompt, _stPreviousBuffer.c_str() + (loc.first_column - 1), false);
634 if (*_piCol < loc.first_column)
636 //pickup separator between expressionsfrom file and add to output
637 printLine(_stPrompt, _stPreviousBuffer.c_str(), false);
638 *_piCol = loc.first_column;
642 //print other full lines
643 for (int i = loc.first_line; i < (loc.last_line - 1) ; i++)
646 std::getline(_File, _stPreviousBuffer);
647 // dont print empty line of function body
648 if (_stPreviousBuffer.size() != 0)
650 printLine(_stPrompt, _stPreviousBuffer.c_str(), false);
655 std::getline(_File, _stPreviousBuffer);
658 int iSize = loc.last_column - 1;
659 std::string stLastLine(_stPreviousBuffer.c_str(), iSize);
660 int iLineLen = (int)_stPreviousBuffer.size();
661 if (iLineLen == iSize)
663 printLine(_stPrompt, stLastLine, true);
668 printLine(_stPrompt, stLastLine, false);
669 *_piCol = loc.last_column;
673 return _stPreviousBuffer;
676 void printLine(const std::string& _stPrompt, const std::string& _stLine, bool _bLF)
680 if (_stPrompt.size() != 0)
682 st = "\n" + _stPrompt;
686 if (_bLF && ConfigVariable::isEmptyLineShow())
691 scilabWrite(st.c_str());
693 /*--------------------------------------------------------------------------*/