* Bug 15146 fixed - lasterror() crashes Scilab when last error message is empty
[scilab.git] / scilab / modules / core / sci_gateway / cpp / sci_lasterror.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2010 - DIGITEO- Antoine ELIAS
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15
16 #include "core_gw.hxx"
17 #include "function.hxx"
18 #include "string.hxx"
19 #include "double.hxx"
20 #include "bool.hxx"
21 #include "configvariable.hxx"
22
23 extern "C"
24 {
25 #include "localization.h"
26 #include "Scierror.h"
27 }
28 /*--------------------------------------------------------------------------*/
29 types::Function::ReturnValue sci_lasterror(types::typed_list &in, int _iRetCount, types::typed_list &out)
30 {
31     bool bClearError = true;
32     if (in.size() > 1)
33     {
34         Scierror(77, _("%s: Wrong number of input argument(s): %d to %d expected."), "lasterror", 0, 1);
35         return types::Function::Error;
36     }
37
38     if (_iRetCount > 4)
39     {
40         Scierror(78, _("%s: Wrong number of output argument(s): %d to %d expected.\n"), "lasterror", 1, 4);
41         return types::Function::Error;
42     }
43
44     if (in.size() == 1)
45     {
46         if (in[0]->isBool() == false || in[0]->getAs<types::Bool>()->isScalar() == false)
47         {
48             Scierror(999, _("%s: Wrong type for input argument #%d: Boolean vector expected.\n"), "lasterror", 1);
49             return types::Function::Error;
50         }
51         bClearError = in[0]->getAs<types::Bool>()->get()[0] == 1; //convert int to bool
52     }
53
54     // check on error number because error message can be empty.
55     if (ConfigVariable::getLastErrorNumber() == 0)
56     {
57         out.push_back(types::Double::Empty());
58     }
59     else
60     {
61         std::wstring wstLastErrorMessage = ConfigVariable::getLastErrorMessage();
62         std::vector<std::wstring> vectLines;
63         std::wistringstream iss(wstLastErrorMessage);
64         std::wstring line;
65         // get all lines
66         while (std::getline( iss, line, L'\n' ))
67         {
68             vectLines.push_back(line);
69         }
70
71         if (!vectLines.empty())
72         {
73             // do not create an empty line if the end of the error message is '\n'
74             if (vectLines.back() == L"")
75             {
76                 vectLines.pop_back();
77             }
78         }
79         else
80         {
81             vectLines.push_back(L"");
82         }
83
84         types::String* StrLastError = new types::String((int)vectLines.size(), 1);
85         // put lines in output
86         for (int i = 0; i < (int)vectLines.size(); i++)
87         {
88             StrLastError->set(i, vectLines[i].c_str());
89         }
90
91         vectLines.clear();
92         out.push_back(StrLastError);
93     }
94
95     if (_iRetCount > 1)
96     {
97         types::Double* pErrorNumber = new types::Double(ConfigVariable::getLastErrorNumber());
98         out.push_back(pErrorNumber);
99
100         if (_iRetCount > 2)
101         {
102             types::Double* pErrorLine = new types::Double(ConfigVariable::getLastErrorLine());
103             out.push_back(pErrorLine);
104
105             if (_iRetCount > 3)
106             {
107                 std::wstring wstLastErrorFunction = ConfigVariable::getLastErrorFunction();
108                 if (wstLastErrorFunction.size() == 0)
109                 {
110                     out.push_back(new types::String(L""));
111                 }
112                 else
113                 {
114                     out.push_back(new types::String(wstLastErrorFunction.c_str()));
115                 }
116             }
117         }
118     }
119
120     if (bClearError)
121     {
122         ConfigVariable::clearLastError();
123     }
124
125     ConfigVariable::setLastErrorCall();
126     return types::Function::OK;
127 }
128 /*--------------------------------------------------------------------------*/