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