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