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