exec and ecestr fixed about parsing error.
[scilab.git] / scilab / modules / functions / sci_gateway / cpp / sci_exec.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 "functions_gw.hxx"
15
16 #include "parser.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"
27 #include "runner.hxx"
28 #include "threadmanagement.hxx"
29 #include "macro.hxx"
30 #include "macrofile.hxx"
31
32 #include <iostream>
33 #include <fstream>
34 #include <string>
35
36 extern "C"
37 {
38 #include "os_string.h"
39 #include "expandPathVariable.h"
40 #include "prompt.h"
41 #include "Scierror.h"
42 #include "localization.h"
43 #include "os_string.h"
44 #include "mopen.h"
45 #include "mclose.h"
46 #include "fullpath.h"
47 #include "PATH_MAX.h"
48 }
49
50 using namespace ast;
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);
54
55 /*--------------------------------------------------------------------------*/
56 types::Function::ReturnValue sci_exec(types::typed_list &in, int _iRetCount, types::typed_list &out)
57 {
58     int promptMode      = 0;//default value at startup, overthise 3 or verbose ";"
59     bool bPromptMode    = false;
60     int iErr            = 0;
61     bool bErrCatch      = false;
62     Exp* pExp           = NULL;
63     int iID             = 0;
64     Parser parser;
65
66     wchar_t* pwstFile = NULL;
67     char* pstFile = NULL;
68
69     std::string stFile;
70     std::ifstream* file = NULL;
71
72     if (ConfigVariable::getStartProcessing() == false)
73     {
74         if (ConfigVariable::getVerbose())
75         {
76             promptMode = 3;
77         }
78         else
79         {
80             promptMode = -1;
81         }
82     }
83
84     if (in.size() < 1 || in.size() > 3)
85     {
86         Scierror(999, _("%s: Wrong number of input arguments: %d to %d expected.\n"), "exec" , 1, 3);
87         return Function::Error;
88     }
89
90     // get mode and errcatch
91     if (in.size() > 1)
92     {
93         //errcatch or mode
94         if (in[1]->isString() && in[1]->getAs<types::String>()->isScalar())
95         {
96             //errcatch
97             String* pS = in[1]->getAs<types::String>();
98             if (os_wcsicmp(pS->get(0), L"errcatch") == 0)
99             {
100                 bErrCatch = true;
101             }
102             else
103             {
104                 if (file)
105                 {
106                     delete pExp;
107                     mclose(iID);
108                     file->close();
109                     delete file;
110                     FREE(pstFile);
111                     FREE(pwstFile);
112                 }
113
114                 Scierror(999, _("%s: Wrong value for input argument #%d: 'errcatch' expected.\n"), "exec", 2);
115                 return Function::Error;
116             }
117
118             if (in.size() > 2)
119             {
120
121                 if (in[2]->isDouble() == false || in[2]->getAs<Double>()->isScalar() == false)
122                 {
123                     if (file)
124                     {
125                         delete pExp;
126                         mclose(iID);
127                         file->close();
128                         delete file;
129                         FREE(pstFile);
130                         FREE(pwstFile);
131                     }
132
133                     //mode
134                     Scierror(999, _("%s: Wrong type for input argument #%d: A integer expected.\n"), "exec", 3);
135                     return Function::Error;
136                 }
137
138                 promptMode = (int)in[2]->getAs<Double>()->getReal()[0];
139                 bPromptMode = true;
140             }
141         }
142         else if (in[1]->isDouble() && in[1]->getAs<Double>()->isScalar())
143         {
144             if (in.size() > 2)
145             {
146                 if (file)
147                 {
148                     delete pExp;
149                     mclose(iID);
150                     file->close();
151                     delete file;
152                     FREE(pstFile);
153                     FREE(pwstFile);
154                 }
155
156                 Scierror(999, _("%s: Wrong value for input argument #%d: 'errcatch' expected.\n"), "exec", 2);
157                 return Function::Error;
158             }
159             //mode
160             promptMode = (int)in[1]->getAs<Double>()->getReal()[0];
161             bPromptMode = true;
162         }
163         else
164         {
165             if (file)
166             {
167                 delete pExp;
168                 mclose(iID);
169                 file->close();
170                 delete file;
171                 FREE(pstFile);
172                 FREE(pwstFile);
173             }
174
175             //not managed
176             Scierror(999, _("%s: Wrong type for input argument #%d: A integer or string expected.\n"), "exec", 2);
177             return Function::Error;
178         }
179     }
180
181     if (in[0]->isString() && in[0]->getAs<types::String>()->isScalar())
182     {
183         //1st argument is a path, parse file and execute it
184         int iParsePathLen = 0;
185         String* pS = in[0]->getAs<types::String>();
186
187         pwstFile = expandPathVariableW(pS->get(0));
188         pstFile = wide_string_to_UTF8(pwstFile);
189         stFile = std::string(pstFile);
190         file = new std::ifstream(pstFile);
191
192         wchar_t* pwstTemp = (wchar_t*)MALLOC(sizeof(wchar_t) * (PATH_MAX * 2));
193         get_full_pathW(pwstTemp, (const wchar_t*)pwstFile, PATH_MAX * 2);
194
195         /*fake call to mopen to show file within file()*/
196         if (mopen(pwstTemp, L"r", 0, &iID) != MOPEN_NO_ERROR)
197         {
198             FREE(pwstTemp);
199             Scierror(999, _("%s: Cannot open file %s.\n"), "exec", pstFile);
200             return Function::Error;
201         }
202
203         parser.parseFile(pwstTemp, L"exec");
204         FREE(pwstTemp);
205         if (parser.getExitStatus() !=  Parser::Succeded)
206         {
207             if (bErrCatch)
208             {
209                 out.push_back(new Double(999));
210                 //to lock last error information
211                 ConfigVariable::setLastErrorCall();
212                 ConfigVariable::setLastErrorMessage(parser.getErrorMessage());
213                 ConfigVariable::setLastErrorNumber(999);
214                 delete parser.getTree();
215                 mclose(iID);
216                 return Function::OK;
217             }
218
219             char* pst = wide_string_to_UTF8(parser.getErrorMessage());
220             Scierror(999, "%s", pst);
221             FREE(pst);
222             delete parser.getTree();
223             mclose(iID);
224             return Function::Error;
225         }
226
227         if (ConfigVariable::getSerialize())
228         {
229             ast::Exp* temp = parser.getTree();
230             if (ConfigVariable::getTimed())
231             {
232                 pExp = callTyper(temp, L"exec");
233             }
234             else
235             {
236                 pExp = callTyper(temp);
237             }
238
239             delete temp;
240         }
241         else
242         {
243             pExp = parser.getTree();
244         }
245     }
246     else if (in[0]->isMacro() || in[0]->isMacroFile())
247     {
248         types::Macro* pMacro = NULL;
249         typed_list input;
250         optional_list optional;
251         typed_list output;
252         ast::ExecVisitor execFunc;
253
254         if (in[0]->isMacroFile())
255         {
256             //1st argument is a macro name, parse and execute it in the current environnement
257             if (in[0]->getAs<MacroFile>()->parse() == false)
258             {
259                 char* pstMacro = wide_string_to_UTF8(in[0]->getAs<MacroFile>()->getName().c_str());
260                 Scierror(999, _("%s: Unable to parse macro '%s'"), "exec", pstMacro);
261                 FREE(pstMacro);
262                 return Function::Error;
263             }
264
265             pMacro = in[0]->getAs<MacroFile>()->getMacro();
266
267         }
268         else //1st argument is a macro name, execute it in the current environnement
269         {
270             pMacro = in[0]->getAs<Macro>();
271         }
272
273         // unable for macro with varargin or varargout
274         auto inputs = pMacro->inputs_get();
275         auto outputs = pMacro->outputs_get();
276         if ((inputs->size() != 0 && inputs->back()->getSymbol().getName() == L"varargin") ||
277                 outputs->size() != 0 && outputs->back()->getSymbol().getName() == L"varargout")
278         {
279             Scierror(999, _("%s: Wrong type for input argument #%d: A macro without varargin and varargout expected.\n"), "exec", 1);
280             return Function::Error;
281         }
282
283         promptMode = 3;
284         pExp = pMacro->getBody();
285     }
286     else
287     {
288         Scierror(999, _("%s: Wrong type for input argument #%d: A string expected.\n"), "exec", 1);
289         return Function::Error;
290     }
291
292     ast::exps_t& LExp = pExp->getAs<SeqExp>()->getExps();
293
294     char pstPrompt[64];
295     //get prompt
296     GetCurrentPrompt(pstPrompt);
297     std::string stPrompt(pstPrompt);
298
299     std::string str;
300     int iCurrentLine = -1; //no data in str
301     int iCurrentCol = 0; //no data in str
302
303     //save current prompt mode
304     int oldVal = ConfigVariable::getPromptMode();
305
306     ConfigVariable::setPromptMode(promptMode);
307
308     types::ThreadId* pThreadMe = ConfigVariable::getThread(__GetCurrentThreadKey());
309
310     for (ast::exps_t::iterator j = LExp.begin(), itEnd = LExp.end() ; j != itEnd ; ++j)
311     {
312         try
313         {
314             if (pThreadMe && pThreadMe->getInterrupt())
315             {
316                 ThreadManagement::SendAstPendingSignal();
317                 pThreadMe->suspend();
318             }
319
320             ast::exps_t::iterator k = j;
321             //mode == 0, print new variable but not command
322             if (file && ConfigVariable::getPromptMode() != 0 && ConfigVariable::getPromptMode() != 2)
323             {
324                 int iLastLine = (*j)->getLocation().last_line;
325                 do
326                 {
327                     str = printExp(*file, *k, stPrompt, &iCurrentLine, &iCurrentCol, str);
328                     iLastLine = (*k)->getLocation().last_line;
329                     k++;
330                 }
331                 while (k != LExp.end() && (*k)->getLocation().first_line == iLastLine);
332
333                 // In case where the line ends by spaces, iCurrentCol is not reset
334                 // by printExp because we don't know if that's the end of the expression
335                 // before go out of the loop. So we have to reset column count
336                 // and print a new line before manage the next line.
337                 if (iCurrentCol != 0)
338                 {
339                     iCurrentCol = 0;
340                     printLine("", "", true);
341                 }
342             }
343             else
344             {
345                 k++;
346             }
347
348
349             ast::exps_t::iterator p = j;
350             for (; p != k; p++)
351             {
352                 bool bImplicitCall = false;
353                 j = p;
354                 //excecute script
355                 //force -1 to prevent recursive call to exec to write in console
356                 //ConfigVariable::setPromptMode(-1);
357                 ExecVisitor execMe;
358                 (*j)->accept(execMe);
359                 //ConfigVariable::setPromptMode(promptMode);
360
361
362                 //to manage call without ()
363                 if (execMe.getResult() != NULL && execMe.getResult()->isCallable())
364                 {
365                     Callable *pCall = execMe.getResult()->getAs<Callable>();
366                     types::typed_list out;
367                     types::typed_list in;
368                     types::optional_list opt;
369
370                     try
371                     {
372                         //in this case of calling, we can return only one values
373                         ExecVisitor execCall;
374                         execCall.setExpectedSize(1);
375                         Function::ReturnValue Ret = pCall->call(in, opt, 1, out, &execCall);
376
377                         if (Ret == Callable::OK)
378                         {
379                             if (out.size() == 0)
380                             {
381                                 execMe.setResult(NULL);
382                             }
383                             else if (out.size() == 1)
384                             {
385                                 out[0]->DecreaseRef();
386                                 execMe.setResult(out[0]);
387                                 bImplicitCall = true;
388                             }
389                             else
390                             {
391                                 for (int i = 0 ; i < static_cast<int>(out.size()) ; i++)
392                                 {
393                                     out[i]->DecreaseRef();
394                                     execMe.setResult(i, out[i]);
395                                 }
396                             }
397                         }
398                         else if (Ret == Callable::Error)
399                         {
400                             if (ConfigVariable::getLastErrorFunction() == L"")
401                             {
402                                 ConfigVariable::setLastErrorFunction(pCall->getName());
403                             }
404
405                             if (pCall->isMacro() || pCall->isMacroFile())
406                             {
407                                 wchar_t szError[bsiz];
408                                 os_swprintf(szError, bsiz, _W("at line % 5d of function %ls called by :\n").c_str(), (*j)->getLocation().first_line, pCall->getName().c_str());
409                                 throw ast::ScilabMessage(szError);
410                             }
411                             else
412                             {
413                                 throw ast::ScilabMessage();
414                             }
415                         }
416                     }
417                     catch (ScilabMessage sm)
418                     {
419                         wostringstream os;
420                         PrintVisitor printMe(os);
421                         (*j)->accept(printMe);
422                         os << std::endl << std::endl;
423                         if (ConfigVariable::getLastErrorFunction() == L"")
424                         {
425                             ConfigVariable::setLastErrorFunction(pCall->getName());
426                         }
427
428                         if (pCall->isMacro() || pCall->isMacroFile())
429                         {
430                             wstring szAllError;
431                             wchar_t szError[bsiz];
432                             os_swprintf(szError, bsiz, _W("at line % 5d of function %ls called by :\n").c_str(), sm.GetErrorLocation().first_line, pCall->getName().c_str());
433                             szAllError = szError + os.str();
434                             os_swprintf(szError, bsiz, _W("at line % 5d of exec file called by :\n").c_str(), (*j)->getLocation().first_line);
435                             szAllError += szError;
436                             throw ast::ScilabMessage(szAllError);
437                         }
438                         else
439                         {
440                             sm.SetErrorMessage(sm.GetErrorMessage() + os.str());
441                             throw sm;
442                         }
443                     }
444                 }
445
446                 //update ans variable
447                 SimpleVar* pVar = dynamic_cast<SimpleVar*>(*j);
448                 //don't output Simplevar and empty result
449                 if (execMe.getResult() != NULL && (pVar == NULL || bImplicitCall))
450                 {
451                     InternalType* pITAns = execMe.getResult();
452                     symbol::Context::getInstance()->put(symbol::Symbol(L"ans"), pITAns);
453                     if ( (*j)->isVerbose() && bErrCatch == false)
454                     {
455                         //TODO manage multiple returns
456                         scilabWriteW(L" ans  =\n\n");
457                         std::wostringstream ostrName;
458                         ostrName << SPACES_LIST << L"ans";
459                         VariableToString(pITAns, ostrName.str().c_str());
460                     }
461                 }
462             }
463         }
464         catch (const ast::InternalAbort& ia)
465         {
466             if (file)
467             {
468                 delete pExp;
469                 mclose(iID);
470                 file->close();
471                 delete file;
472                 FREE(pstFile);
473                 FREE(pwstFile);
474             }
475
476             //restore previous prompt mode
477             ConfigVariable::setPromptMode(oldVal);
478
479             throw ia;
480         }
481         catch (const ScilabMessage& sm)
482         {
483             scilabErrorW(sm.GetErrorMessage().c_str());
484
485             CallExp* pCall = dynamic_cast<CallExp*>(*j);
486             if (pCall != NULL)
487             {
488                 //to print call expression only of it is a macro
489                 ExecVisitor execFunc;
490                 pCall->getName().accept(execFunc);
491
492                 if (execFunc.getResult() != NULL &&
493                         (execFunc.getResult()->isMacro() || execFunc.getResult()->isMacroFile()))
494                 {
495                     wostringstream os;
496
497                     //add function failed
498                     PrintVisitor printMe(os);
499                     pCall->accept(printMe);
500                     os << std::endl;
501
502                     //add info on file failed
503                     wchar_t szError[bsiz];
504                     os_swprintf(szError, bsiz, _W("at line % 5d of exec file called by :\n").c_str(), (*j)->getLocation().first_line);
505                     os << szError;
506
507                     if (ConfigVariable::getLastErrorFunction() == L"")
508                     {
509                         ConfigVariable::setLastErrorFunction(execFunc.getResult()->getAs<Callable>()->getName());
510                     }
511
512                     Location location = (*j)->getLocation();
513                     if (file)
514                     {
515                         delete pExp;
516                         mclose(iID);
517                         file->close();
518                         delete file;
519                         FREE(pstFile);
520                         FREE(pwstFile);
521                     }
522
523                     //restore previous prompt mode
524                     ConfigVariable::setPromptMode(oldVal);
525                     throw ast::ScilabMessage(os.str(), 0, location);
526                 }
527             }
528
529             Location location = (*j)->getLocation();
530             if (file)
531             {
532                 delete pExp;
533                 mclose(iID);
534                 file->close();
535                 delete file;
536                 FREE(pstFile);
537                 FREE(pwstFile);
538             }
539
540             throw ast::ScilabMessage(location);
541         }
542         catch (const ast::ScilabError& se)
543         {
544             if (ConfigVariable::getLastErrorNumber() == 0)
545             {
546                 ConfigVariable::setLastErrorMessage(se.GetErrorMessage());
547                 ConfigVariable::setLastErrorNumber(se.GetErrorNumber());
548                 ConfigVariable::setLastErrorLine(se.GetErrorLocation().first_line);
549                 ConfigVariable::setLastErrorFunction(wstring(L""));
550             }
551
552             //store message
553             iErr = ConfigVariable::getLastErrorNumber();
554             if (bErrCatch == false)
555             {
556                 if (file)
557                 {
558                     //print failed command
559                     scilabError(getExpression(stFile, *j).c_str());
560                     scilabErrorW(L"\n");
561                 }
562
563                 //write error
564                 scilabErrorW(se.GetErrorMessage().c_str());
565
566                 //write position
567                 wchar_t szError[bsiz];
568                 os_swprintf(szError, bsiz, _W("at line % 5d of exec file called by :\n").c_str(), (*j)->getLocation().first_line);
569                 scilabErrorW(szError);
570                 if (file)
571                 {
572                     delete pExp;
573                     mclose(iID);
574                     file->close();
575                     delete file;
576                     FREE(pstFile);
577                     FREE(pwstFile);
578                 }
579
580                 //restore previous prompt mode
581                 ConfigVariable::setPromptMode(oldVal);
582                 //throw ast::ScilabMessage(szError, 1, (*j)->getLocation());
583                 //print already done, so just foward exception but with message
584                 throw ast::ScilabError();
585             }
586             break;
587         }
588     }
589
590     //restore previous prompt mode
591     ConfigVariable::setPromptMode(oldVal);
592
593     if (bErrCatch)
594     {
595         out.push_back(new Double(iErr));
596         //to lock last error information
597         ConfigVariable::setLastErrorCall();
598     }
599
600     if (file)
601     {
602         delete pExp;
603         mclose(iID);
604         file->close();
605         delete file;
606         FREE(pstFile);
607         FREE(pwstFile);
608     }
609
610     return Function::OK;
611 }
612
613 std::string getExpression(const std::string& _stFile, Exp* _pExp)
614 {
615     std::string out;
616     std::string stBuffer;
617     int iLine = 0;
618     Location loc = _pExp->getLocation();
619     std::ifstream file(_stFile.c_str());
620
621     //bypass previous lines
622     for (int i = 0 ; i < loc.first_line; i++)
623     {
624         std::getline(file, stBuffer);
625     }
626
627     if (loc.first_line == loc.last_line)
628     {
629         int iStart = loc.first_column - 1;
630         int iEnd = loc.last_column - 1;
631         int iLen = iEnd - iStart;
632         out += string(stBuffer.c_str() + iStart, iLen);
633     }
634     else
635     {
636         //
637
638         //first line, entire or not
639         out += string(stBuffer.c_str() + loc.first_column - 1);
640         out += "\n";
641
642         //print other full lines
643         for (int i = loc.first_line; i < (loc.last_line - 1) ; i++)
644         {
645             std::getline(file, stBuffer);
646             out += stBuffer;
647             out += "\n";
648         }
649
650
651         //last line, entire or not
652         getline(file, stBuffer);
653         out += string(stBuffer.c_str(), loc.last_column - 1);
654         out += "\n";
655     }
656     return out;
657 }
658
659 std::string printExp(std::ifstream& _File, Exp* _pExp, const std::string& _stPrompt, int* _piLine /* in/out */, int* _piCol /* in/out */, std::string& _stPreviousBuffer)
660 {
661     //case 1, exp is on 1 line and take the entire line
662
663     //case 2, exp is multiline
664
665     //case 3, exp is part of a line.
666     //ex : 3 exp on the same line a = 1; b = 2; c = 3;
667
668     //case 4, exp is multiline but start and/or finish in the middle of a line
669     //ex :
670     //a = 10;for i = 1 : a
671     //  a
672     //end, b = 1;
673
674     Location loc = _pExp->getLocation();
675
676     //positionning file curser at loc.first_line
677     {
678         //strange case, current position is after the wanted position
679         if (*_piLine > loc.first_line)
680         {
681             //reset line counter and restart reading at the start of the file.
682             *_piLine = -1;
683             _File.seekg( 0, ios_base::beg );
684         }
685
686         //bypass previous lines
687         for (int i = *_piLine ; i < loc.first_line - 1; i++)
688         {
689
690             (*_piLine)++;
691             if ((*_piLine) != (loc.first_line - 1))
692             {
693                 //empty line but not sequential lines
694                 printLine("", "", true);
695             }
696             std::getline(_File, _stPreviousBuffer);
697         }
698     }
699
700     if (loc.first_line == loc.last_line)
701     {
702         //1 line
703         int iStart = loc.first_column - 1;
704         int iEnd = loc.last_column - 1;
705         int iLen = iEnd - iStart;
706         std::string strLastLine(_stPreviousBuffer.c_str() + iStart, iLen);
707         int iExpLen = iLen;
708         int iLineLen = (int)_stPreviousBuffer.size();
709         //printLine(_pstPrompt, strLastLine, true, false);
710
711         if (iStart == 0 && iExpLen == iLineLen)
712         {
713             //entire line
714             if (*_piCol)
715             {
716                 //blank char at the end of previous line
717                 printLine("", "", true);
718             }
719             printLine(_stPrompt, strLastLine, true);
720             *_piCol = 0;
721         }
722         else
723         {
724             if (iStart == 0)
725             {
726                 //begin of line
727                 if (*_piCol)
728                 {
729                     //blank char at the end of previous line
730                     printLine("", "", true);
731                 }
732                 printLine(_stPrompt, strLastLine, false);
733                 *_piCol = loc.last_column;
734             }
735             else
736             {
737                 if (*_piCol == 0)
738                 {
739                     printLine(_stPrompt, "", false);
740                     (*_piCol)++;
741                 }
742
743                 if (*_piCol < loc.first_column)
744                 {
745                     //pickup separator between expressionsfrom file and add to output
746                     int iSize = loc.first_column - *_piCol;
747                     std::string stTemp(_stPreviousBuffer.c_str() +  (*_piCol - 1), iSize);
748                     printLine("", stTemp, false);
749                     *_piCol = loc.first_column;
750                 }
751
752                 if (iEnd == iLineLen)
753                 {
754                     printLine("", strLastLine, true);
755                     *_piCol = 0;
756                 }
757                 else
758                 {
759                     printLine("", strLastLine, false);
760                     *_piCol = loc.last_column;
761                 }
762             }
763         }
764     }
765     else
766     {
767         //multiline
768
769         if (loc.first_column == 1)
770         {
771             if (*_piCol)
772             {
773                 //blank char at the end of previous line
774                 printLine("", "", true);
775             }
776             printLine(_stPrompt, _stPreviousBuffer.c_str() + (loc.first_column - 1), false);
777         }
778         else
779         {
780             if (*_piCol < loc.first_column)
781             {
782                 //pickup separator between expressionsfrom file and add to output
783                 printLine(_stPrompt, _stPreviousBuffer.c_str(), false);
784                 *_piCol = loc.first_column;
785             }
786         }
787
788         //print other full lines
789         for (int i = loc.first_line; i < (loc.last_line - 1) ; i++)
790         {
791             (*_piLine)++;
792             std::getline(_File, _stPreviousBuffer);
793             // dont print empty line of function body
794             if (_stPreviousBuffer.size() != 0)
795             {
796                 printLine(_stPrompt, _stPreviousBuffer.c_str(), false);
797             }
798         }
799
800         //last line
801         std::getline(_File, _stPreviousBuffer);
802         (*_piLine)++;
803
804         int iSize = loc.last_column - 1;
805         std::string stLastLine(_stPreviousBuffer.c_str(), iSize);
806         int iLineLen = (int)_stPreviousBuffer.size();
807         if (iLineLen == iSize)
808         {
809             printLine(_stPrompt, stLastLine, true);
810             *_piCol = 0;
811         }
812         else
813         {
814             printLine(_stPrompt, stLastLine, false);
815             *_piCol = loc.last_column;
816         }
817     }
818
819     return _stPreviousBuffer;
820 }
821
822 void printLine(const std::string& _stPrompt, const std::string& _stLine, bool _bLF)
823 {
824     std::string st;
825
826     if (_stPrompt.size() != 0)
827     {
828         st = "\n" + _stPrompt;
829     }
830
831     st += _stLine;
832     if (_bLF && ConfigVariable::isEmptyLineShow())
833     {
834         st += "\n";
835     }
836
837     scilabWrite(st.c_str());
838 }
839 /*--------------------------------------------------------------------------*/