coverity: fix #1401290 to #1401299 ; use default values on error
[scilab.git] / scilab / modules / ui_data / src / cpp / BrowseVarManager.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2010 - DIGITEO - Allan CORNET
4  * Copyright (C) 2010 - DIGITEO - Bruno JOFRET
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 #include <iostream>
18 #include <sstream>
19 #include <string>
20 #include <iterator>
21 #include <set>
22 #include <cmath>
23 #include "alltypes.hxx"
24 #include "types_tools.hxx"
25
26 #include "BrowseVar.hxx"
27 #ifdef _MSC_VER
28 #ifdef max
29 #undef max
30 #endif
31 #ifdef min
32 #undef min
33 #endif
34 #endif
35 #include "context.hxx"
36
37 extern "C"
38 {
39 #include "BrowseVarManager.h"
40 #include "localization.h"
41 #include "sci_malloc.h"
42 #include "BOOL.h"
43 #include "getScilabJavaVM.h"
44 #include "Scierror.h"
45 #include "freeArrayOfString.h"
46 #include "os_string.h"
47 #include "api_scilab.h"
48 #include "sci_types.h"
49 #include "sciprint.h"
50 }
51
52 #define N_A             "N/A"
53 #define EMPTY_MATRIX    "[ ]"
54 #define EMPTY_CELL      "{}"
55 #define EMPTY_LIST      "()"
56 #define LOCAL_STR       "local"
57 #define GLOBAL_STR      "global"
58 #define INHERITED_STR   "inherited"
59 #define NEG_INF_STR     "-Inf"
60 #define INF_STR         "Inf"
61 #define NAN_STR         "NaN"
62 #define PLUS_STR        " + "
63 #define MINUS_STR       " - "
64 #define I_STR           "i"
65 #define LBRACKET_STR    "["
66 #define RBRACKET_STR    "]"
67 #define COMMA_STR       ", "
68 #define SEMICOLON_STR   "; "
69
70 using namespace org_scilab_modules_ui_data;
71 using std::string;
72
73 static std::set<string> createScilabDefaultVariablesSet();
74 static char * getListName(char * variableName);
75 static std::string formatMatrix(int nbRows, int nbCols, double *pdblReal, double *pdblImg);
76 static char * valueToDisplay(types::InternalType* pIT);
77 void OpenBrowseVar()
78 {
79     BrowseVar::openVariableBrowser(getScilabJavaVM());
80     SetBrowseVarData();
81 }
82
83 void UpdateBrowseVar()
84 {
85     if (BrowseVar::isVariableBrowserOpened(getScilabJavaVM()))
86     {
87         SetBrowseVarData();
88     }
89 }
90
91 void SetBrowseVarData()
92 {
93     SciErr err;
94     int iLocalVariablesUsed = 0;
95     int i = 0;
96
97     symbol::Context* ctx = symbol::Context::getInstance();
98
99     std::list<symbol::Variable*> lstVars;
100     std::list<symbol::Library*> lstLibs;
101
102     iLocalVariablesUsed = ctx->getVarsToVariableBrowser(lstVars);
103     iLocalVariablesUsed += ctx->getLibsToVariableBrowser(lstLibs);
104
105     char **pstAllVariableNames = new char*[iLocalVariablesUsed]();
106     char **pstAllVariableVisibility = new char*[iLocalVariablesUsed]();
107     char **pstAllVariableListTypes = new char*[iLocalVariablesUsed]();
108     int *piAllVariableBytes = new int[iLocalVariablesUsed]();
109     char **pstAllVariableSizes = new char*[iLocalVariablesUsed]();
110     int *piAllVariableTypes = new int[iLocalVariablesUsed]();
111     int *piAllVariableIntegerTypes = new int[iLocalVariablesUsed]();
112     bool *piAllVariableFromUser = new bool[iLocalVariablesUsed]();
113     /* Necessary for the plots in the var browser */
114     int *piAllVariableNbRows = new int[iLocalVariablesUsed]();
115     int *piAllVariableNbCols = new int[iLocalVariablesUsed]();
116
117     int nbRows, nbCols;
118     char *sizeStr = NULL;
119
120     std::set<string> scilabDefaultVariablesSet = createScilabDefaultVariablesSet();
121     int iLevel = ctx->getScopeLevel();
122
123     // for each local variable get information
124     for (auto var : lstVars)
125     {
126         //get top level value
127         symbol::ScopedVariable* sv = var->top();
128         //get value
129         types::InternalType* pIT = sv->m_pIT;
130
131         // get name
132         pstAllVariableNames[i] = wide_string_to_UTF8(var->getSymbol().getName().data());
133
134         // get visibility
135         if (sv->m_globalVisible == true)
136         {
137             pstAllVariableVisibility[i] = os_strdup(GLOBAL_STR);
138             pIT = var->getGlobalValue();
139         }
140         else if (sv->m_iLevel != iLevel)
141         {
142             pstAllVariableVisibility[i] = os_strdup(INHERITED_STR);
143         }
144         else
145         {
146             pstAllVariableVisibility[i] = os_strdup(LOCAL_STR);
147         }
148
149         // type with Scilab < 6 compatibility (structs and cells have type 17)
150         err = getVarType(NULL, (int*)pIT, &piAllVariableTypes[i]);
151         if (err.iErr)
152         {
153             piAllVariableTypes[i] = 0;
154         }
155         err = getVarDimension(NULL, (int*)pIT, &nbRows, &nbCols);
156         if (err.iErr)
157         {
158             nbRows = 0;
159             nbCols = 0;
160         }
161
162         if (pIT->isArrayOf() || pIT->isSparse())
163         {
164             int nbRows = pIT->getAs<types::GenericType>()->getRows();
165             int nbCols = pIT->getAs<types::GenericType>()->getCols();
166             piAllVariableNbRows[i] = nbRows;
167             piAllVariableNbCols[i] = nbCols;
168             if (nbRows * nbCols == 0)
169             {
170                 pstAllVariableSizes[i] = pIT->isCell() ? os_strdup(EMPTY_CELL) : os_strdup(EMPTY_MATRIX);
171             }
172             else if (pIT->isArrayOf())
173             {
174                 pstAllVariableSizes[i] = valueToDisplay(pIT);
175             }
176             else
177             {
178                 std::string sizeString = std::to_string(nbRows) + "x" + std::to_string(nbCols);
179                 pstAllVariableSizes[i] =  os_strdup(sizeString.data());
180             }
181         }
182         else if (pIT->isMList() || pIT->isTList() || pIT->isList() )
183         {
184             pstAllVariableSizes[i] = pIT->getAs<types::List>()->getSize() == 0 ? os_strdup(EMPTY_LIST) : os_strdup(N_A);
185         }
186         else
187         {
188             pstAllVariableSizes[i] =  os_strdup(N_A);
189         }
190
191         if (piAllVariableTypes[i] == sci_ints)
192         {
193             // Integer case
194             int iPrec       = 0;
195             err = getMatrixOfIntegerPrecision(NULL, (int*)pIT, &iPrec);
196             if (err.iErr)
197             {
198                 return;
199             }
200             switch (iPrec)
201             {
202                 case SCI_INT8:
203                     piAllVariableIntegerTypes[i] = 8;
204                     break;
205                 case SCI_INT16:
206                     piAllVariableIntegerTypes[i] = 16;
207                     break;
208                 case SCI_INT32:
209                     piAllVariableIntegerTypes[i] = 32;
210                     break;
211 #ifdef __SCILAB_INT64__
212                 case SCI_INT64:
213                     piAllVariableIntegerTypes[i] = 64;
214                     break;
215 #endif
216                 default:
217                     piAllVariableIntegerTypes[i] = 0; // Should never occurs
218                     break;
219             }
220         }
221         else
222         {
223             piAllVariableIntegerTypes[i] = -1;
224         }
225
226         if (pIT->isTList() || pIT->isMList())
227         {
228             pstAllVariableListTypes[i] = getListName(pstAllVariableNames[i]);
229         }
230         else if (pIT->isStruct())
231         {
232             piAllVariableTypes[i] = sci_struct;
233             pstAllVariableListTypes[i] = os_strdup("");
234         }
235         else if (pIT->isCell())
236         {
237             piAllVariableTypes[i] = sci_cell;
238             pstAllVariableListTypes[i] = os_strdup("");
239         }
240         else
241         {
242             pstAllVariableListTypes[i] = os_strdup("");
243         }
244
245         if (scilabDefaultVariablesSet.find(string(pstAllVariableNames[i])) == scilabDefaultVariablesSet.end() && piAllVariableTypes[i] != sci_lib)
246         {
247             piAllVariableFromUser[i] = TRUE;
248         }
249         else
250         {
251             piAllVariableFromUser[i] = FALSE;
252         }
253
254         int bytesWithoutOverHead;
255         pIT->getMemory(&bytesWithoutOverHead, &piAllVariableBytes[i]);
256
257         ++i;
258     }
259
260     for (auto lib : lstLibs)
261     {
262         //get top level value
263         symbol::ScopedLibrary* sl = lib->top();
264
265         // get name
266         pstAllVariableNames[i] = wide_string_to_UTF8(lib->getSymbol().getName().data());
267
268         // get visibility
269         if (sl->m_iLevel != iLevel)
270         {
271             pstAllVariableVisibility[i] = os_strdup(INHERITED_STR);
272         }
273         else
274         {
275             pstAllVariableVisibility[i] = os_strdup(LOCAL_STR);
276         }
277         //type
278         piAllVariableTypes[i] = sci_lib;
279         pstAllVariableSizes[i] = os_strdup(N_A);
280         piAllVariableIntegerTypes[i] = -1;
281         pstAllVariableListTypes[i] = os_strdup("");
282         piAllVariableFromUser[i] = FALSE;
283         piAllVariableNbRows[i] = 1;
284         piAllVariableNbCols[i] = 1;
285         //get value and bytes
286         types::GenericType* pIT = sl->m_pLib;
287         int bytesWithoutOverHead;
288         pIT->getMemory(&bytesWithoutOverHead, &piAllVariableBytes[i]);
289
290         ++i;
291     }
292
293     // Launch Java Variable Browser through JNI
294     BrowseVar::setVariableBrowserData(getScilabJavaVM(),
295                                       pstAllVariableNames, iLocalVariablesUsed,
296                                       piAllVariableBytes, iLocalVariablesUsed,
297                                       piAllVariableTypes, iLocalVariablesUsed,
298                                       piAllVariableIntegerTypes, iLocalVariablesUsed,
299                                       pstAllVariableListTypes, iLocalVariablesUsed,
300                                       pstAllVariableSizes, iLocalVariablesUsed,
301                                       piAllVariableNbRows, iLocalVariablesUsed,
302                                       piAllVariableNbCols, iLocalVariablesUsed,
303                                       pstAllVariableVisibility, iLocalVariablesUsed,
304                                       piAllVariableFromUser, iLocalVariablesUsed);
305
306     for (int i = 0; i < iLocalVariablesUsed; ++i)
307     {
308         FREE(pstAllVariableNames[i]);
309         FREE(pstAllVariableVisibility[i]);
310         FREE(pstAllVariableSizes[i]);
311         FREE(pstAllVariableListTypes[i]);
312     }
313
314     delete[] pstAllVariableNames;
315     delete[] pstAllVariableVisibility;
316     delete[] pstAllVariableSizes;
317     delete[] pstAllVariableListTypes;
318
319     delete[] piAllVariableFromUser;
320     delete[] piAllVariableBytes;
321     delete[] piAllVariableTypes;
322     delete[] piAllVariableIntegerTypes;
323     delete[] piAllVariableNbRows;
324     delete[] piAllVariableNbCols;
325 }
326
327 /*--------------------------------------------------------------------------*/
328 static std::set<string> createScilabDefaultVariablesSet()
329 {
330     string arr[] =
331     {
332         "home",
333         "PWD",
334         "%tk",
335         "%pvm",
336         "MSDOS",
337         "%F",
338         "%T",
339         "%f",
340         "%t",
341         "%e",
342         "%pi",
343         "%modalWarning",
344         "%nan",
345         "%inf",
346         "SCI",
347         "WSCI",
348         "SCIHOME",
349         "TMPDIR",
350         "%gui",
351         "%fftw",
352         "%helps",
353         "%eps",
354         "%io",
355         "%i",
356         "demolist",
357         "%z",
358         "%s",
359         "$",
360         "%toolboxes",
361         "%toolboxes_dir",
362         "TICTOC",
363         "%helps_modules",
364         "%_atoms_cache",
365         "evoid", // Constant for external object
366         "jvoid", // Constant for external object Java (jims)
367         "jnull", // Constant for external object Java (jims)
368         "enull"  // Constant for external object
369     };
370     int i = 0;
371
372 #define NBELEMENT 37
373     std::set<string> ScilabDefaultVariables;
374
375     for (i = 0; i < NBELEMENT; i++)
376     {
377         ScilabDefaultVariables.insert(arr[i]);
378     }
379
380     return ScilabDefaultVariables;
381 }
382
383 static char * getListName(char * variableName)
384 {
385     SciErr sciErr;
386     int *piAddr = NULL;
387     int* piAddr1 = NULL;
388     int iRows = 0;
389     int iCols = 0;
390     char **pstType;
391     char *tmpChar;
392     sciErr = getVarAddressFromName(NULL, variableName, &piAddr);
393     if (sciErr.iErr)
394     {
395         return os_strdup("");
396     }
397
398     sciErr = getListItemAddress(NULL, piAddr, 1, &piAddr1);
399     if (sciErr.iErr)
400     {
401         return os_strdup("");
402     }
403
404     if (getAllocatedMatrixOfString(NULL, piAddr1, &iRows, &iCols, &pstType))
405     {
406
407         return os_strdup("");
408     }
409     tmpChar = os_strdup(pstType[0]);
410     freeAllocatedMatrixOfString(iRows, iCols, pstType);
411     return tmpChar;
412 }
413
414 static char *valueToDisplay(types::InternalType* pIT)
415 {
416     types::GenericType *pGT = pIT->getAs<types::GenericType>();
417     int *piDims = pGT->getDimsArray();
418
419     if (pIT->isDouble() && pGT->getDims() < 3 && pGT->getSize() <= 4)
420     {
421         // 4 is the dimension max to which display the content
422         types::Double* pD = pIT->getAs<types::Double>();
423         // Small double value, display it
424         double* pdblReal = nullptr;
425         double* pdblImg = nullptr;
426         pdblReal = pD->get();
427
428         if (pD->isComplex())
429         {
430             pdblImg = pD->getImg();
431         }
432
433         return os_strdup(formatMatrix(piDims[0], piDims[1], pdblReal, pdblImg).c_str());
434     }
435     else
436     {
437         std::string sizeStr = std::to_string(piDims[0]);
438         for (int i = 1; i < pGT->getDims(); i++)
439         {
440             sizeStr.append("x");
441             sizeStr.append(std::to_string(piDims[i]));
442         }
443
444         return os_strdup(sizeStr.data());
445     }
446 }
447
448 std::string addDouble(double dbl)
449 {
450 #define PRECISION_DISPLAY 3
451     std::ostringstream os;
452     if (ISNAN(dbl))
453     {
454         os << NAN_STR;
455     }
456     else if (finite(dbl))
457     {
458         os.precision(PRECISION_DISPLAY);
459         os << dbl; // Convert the double to string
460     }
461     else
462     {
463         if (dbl > 0)
464         {
465             os << INF_STR;
466         }
467         else
468         {
469             os << NEG_INF_STR;
470         }
471     }
472
473     return os.str();
474 }
475 std::string formatMatrix(int nbRows, int nbCols, double *pdblReal, double *pdblImg)
476 {
477     int i, j ;
478     if (nbRows * nbCols == 1)
479     {
480         std::ostringstream os;
481         std::string formatted = addDouble(pdblReal[0]);
482         if (pdblImg)
483         {
484             double img = pdblImg[0];
485             if (img > 0)
486             {
487                 formatted += PLUS_STR;
488             }
489             else
490             {
491                 formatted += MINUS_STR;
492             }
493             formatted += addDouble(std::fabs(img));
494             formatted += I_STR;
495         }
496         return formatted;
497     }
498
499     std::string formatted = LBRACKET_STR;
500     for (j = 0 ; j < nbRows ; j++)
501     {
502         for (i = 0 ; i < nbCols ; i++)
503         {
504             /* Display the formatted matrix ... the way the user
505              * expect */
506             formatted += addDouble(pdblReal[i * nbRows + j]);
507             if (pdblImg)
508             {
509                 double img = pdblImg[i * nbRows + j];
510                 if (img > 0)
511                 {
512                     formatted += PLUS_STR;
513                 }
514                 else
515                 {
516                     formatted += MINUS_STR;
517                 }
518
519                 formatted += addDouble(std::fabs(img));
520                 formatted += I_STR;
521             }
522
523
524             if (i + 1 != nbCols) // Not the last element of the matrix
525             {
526                 formatted += COMMA_STR;
527             }
528         }
529         if (j + 1 != nbRows) // Not the last line of the matrix
530         {
531             formatted += SEMICOLON_STR;
532         }
533     }
534     return formatted + "]";
535 }