Bug 15310 fixed: isdef regression for void type repaired bis
[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 }
49
50 #define N_A             "N/A"
51 #define EMPTY_MATRIX    "[ ]"
52 #define LOCAL_STR       "local"
53 #define GLOBAL_STR      "global"
54 #define INHERITED_STR   "inherited"
55 #define STRUCT_STR      "st"
56 #define NEG_INF_STR     "-Inf"
57 #define INF_STR         "Inf"
58 #define NAN_STR         "NaN"
59 #define PLUS_STR        " + "
60 #define MINUS_STR       " - "
61 #define I_STR           "i"
62 #define LBRACKET_STR    "["
63 #define RBRACKET_STR    "]"
64 #define COMMA_STR       ", "
65 #define SEMICOLON_STR   "; "
66
67 using namespace org_scilab_modules_ui_data;
68 using std::string;
69
70 static std::set<string> createScilabDefaultVariablesSet();
71 static char * getListName(char * variableName);
72 static std::string formatMatrix(int nbRows, int nbCols, double *pdblReal, double *pdblImg);
73 static char * valueToDisplay(types::InternalType* pIT);
74 void OpenBrowseVar()
75 {
76     BrowseVar::openVariableBrowser(getScilabJavaVM());
77     SetBrowseVarData();
78 }
79
80 void UpdateBrowseVar()
81 {
82     if (BrowseVar::isVariableBrowserOpened(getScilabJavaVM()))
83     {
84         SetBrowseVarData();
85     }
86 }
87
88 void SetBrowseVarData()
89 {
90     SciErr err;
91     int iLocalVariablesUsed = 0;
92     int i = 0;
93
94     symbol::Context* ctx = symbol::Context::getInstance();
95
96     std::list<symbol::Variable*> lstVars;
97     std::list<symbol::Library*> lstLibs;
98
99     iLocalVariablesUsed = ctx->getVarsToVariableBrowser(lstVars);
100     iLocalVariablesUsed += ctx->getLibsToVariableBrowser(lstLibs);
101
102     char **pstAllVariableNames = new char*[iLocalVariablesUsed]();
103     char **pstAllVariableVisibility = new char*[iLocalVariablesUsed]();
104     char **pstAllVariableListTypes = new char*[iLocalVariablesUsed]();
105     int *piAllVariableBytes = new int[iLocalVariablesUsed]();
106     char **pstAllVariableSizes = new char*[iLocalVariablesUsed]();
107     int *piAllVariableTypes = new int[iLocalVariablesUsed]();
108     int *piAllVariableIntegerTypes = new int[iLocalVariablesUsed]();
109     bool *piAllVariableFromUser = new bool[iLocalVariablesUsed]();
110     /* Necessary for the plots in the var browser */
111     int *piAllVariableNbRows = new int[iLocalVariablesUsed]();
112     int *piAllVariableNbCols = new int[iLocalVariablesUsed]();
113
114     int nbRows, nbCols;
115     char *sizeStr = NULL;
116
117     std::set<string> scilabDefaultVariablesSet = createScilabDefaultVariablesSet();
118     int iLevel = ctx->getScopeLevel();
119
120     // for each local variable get information
121     for (auto var : lstVars)
122     {
123         //get top level value
124         symbol::ScopedVariable* sv = var->top();
125         //get value
126         types::InternalType* pIT = sv->m_pIT;
127
128         // get name
129         pstAllVariableNames[i] = wide_string_to_UTF8(var->getSymbol().getName().data());
130
131         // get visibility
132         if (sv->m_globalVisible == true)
133         {
134             pstAllVariableVisibility[i] = os_strdup(GLOBAL_STR);
135             pIT = var->getGlobalValue();
136         }
137         else if (sv->m_iLevel != iLevel)
138         {
139             pstAllVariableVisibility[i] = os_strdup(INHERITED_STR);
140         }
141         else
142         {
143             pstAllVariableVisibility[i] = os_strdup(LOCAL_STR);
144         }
145
146         // type
147         err = getVarType(NULL, (int*)pIT, &piAllVariableTypes[i]);
148         if (!err.iErr)
149         {
150             err = getVarDimension(NULL, (int*)pIT, &nbRows, &nbCols);
151         }
152
153         if (err.iErr)
154         {
155             pstAllVariableSizes[i] = os_strdup(N_A);
156         }
157         else if (nbRows * nbCols == 0)
158         {
159             pstAllVariableSizes[i] = os_strdup(EMPTY_MATRIX);
160         }
161         else
162         {
163             pstAllVariableSizes[i] = valueToDisplay(pIT);
164             piAllVariableNbRows[i] = nbRows;
165             piAllVariableNbCols[i] = nbCols;
166         }
167
168         if (piAllVariableTypes[i] == sci_ints)
169         {
170             // Integer case
171             int iPrec       = 0;
172             err = getMatrixOfIntegerPrecision(NULL, (int*)pIT, &iPrec);
173             switch (iPrec)
174             {
175                 case SCI_INT8:
176                     piAllVariableIntegerTypes[i] = 8;
177                     break;
178                 case SCI_INT16:
179                     piAllVariableIntegerTypes[i] = 16;
180                     break;
181                 case SCI_INT32:
182                     piAllVariableIntegerTypes[i] = 32;
183                     break;
184 #ifdef __SCILAB_INT64__
185                 case SCI_INT64:
186                     piAllVariableIntegerTypes[i] = 64;
187                     break;
188 #endif
189                 default:
190                     piAllVariableIntegerTypes[i] = 0; // Should never occurs
191                     break;
192             }
193         }
194         else
195         {
196             piAllVariableIntegerTypes[i] = -1;
197         }
198
199         if (pIT->isTList() || pIT->isMList())
200         {
201             pstAllVariableListTypes[i] = getListName(pstAllVariableNames[i]);
202         }
203         else if (pIT->isStruct())
204         {
205             pstAllVariableListTypes[i] = os_strdup(STRUCT_STR);
206         }
207         else
208         {
209             pstAllVariableListTypes[i] = os_strdup("");
210         }
211
212         if (scilabDefaultVariablesSet.find(string(pstAllVariableNames[i])) == scilabDefaultVariablesSet.end() && piAllVariableTypes[i] != sci_lib)
213         {
214             piAllVariableFromUser[i] = TRUE;
215         }
216         else
217         {
218             piAllVariableFromUser[i] = FALSE;
219         }
220         
221         int bytesWithoutOverHead;
222         pIT->getMemory(&bytesWithoutOverHead, &piAllVariableBytes[i]);
223         
224         ++i;
225     }
226
227     for (auto lib : lstLibs)
228     {
229         //get top level value
230         symbol::ScopedLibrary* sl = lib->top();
231
232         // get name
233         pstAllVariableNames[i] = wide_string_to_UTF8(lib->getSymbol().getName().data());
234
235         // get visibility
236         if (sl->m_iLevel != iLevel)
237         {
238             pstAllVariableVisibility[i] = os_strdup(INHERITED_STR);
239         }
240         else
241         {
242             pstAllVariableVisibility[i] = os_strdup(LOCAL_STR);
243         }
244         //type
245         piAllVariableTypes[i] = sci_lib;
246         pstAllVariableSizes[i] = os_strdup(N_A);
247         piAllVariableIntegerTypes[i] = -1;
248         pstAllVariableListTypes[i] = os_strdup("");
249         piAllVariableFromUser[i] = FALSE;
250         piAllVariableNbRows[i] = 1;
251         piAllVariableNbCols[i] = 1;
252         //get value and bytes
253         types::GenericType* pIT = sl->m_pLib;
254         int bytesWithoutOverHead;
255         pIT->getMemory(&bytesWithoutOverHead, &piAllVariableBytes[i]);
256
257         ++i;
258     }
259     // Launch Java Variable Browser through JNI
260     BrowseVar::setVariableBrowserData(getScilabJavaVM(),
261                                       pstAllVariableNames, iLocalVariablesUsed,
262                                       piAllVariableBytes, iLocalVariablesUsed,
263                                       piAllVariableTypes, iLocalVariablesUsed,
264                                       piAllVariableIntegerTypes, iLocalVariablesUsed,
265                                       pstAllVariableListTypes, iLocalVariablesUsed,
266                                       pstAllVariableSizes, iLocalVariablesUsed,
267                                       piAllVariableNbRows, iLocalVariablesUsed,
268                                       piAllVariableNbCols, iLocalVariablesUsed,
269                                       pstAllVariableVisibility, iLocalVariablesUsed,
270                                       piAllVariableFromUser, iLocalVariablesUsed);
271
272     for (int i = 0; i < iLocalVariablesUsed; ++i)
273     {
274         FREE(pstAllVariableNames[i]);
275         FREE(pstAllVariableVisibility[i]);
276         FREE(pstAllVariableSizes[i]);
277         FREE(pstAllVariableListTypes[i]);
278     }
279
280     delete[] pstAllVariableNames;
281     delete[] pstAllVariableVisibility;
282     delete[] pstAllVariableSizes;
283     delete[] pstAllVariableListTypes;
284
285     delete[] piAllVariableFromUser;
286     delete[] piAllVariableBytes;
287     delete[] piAllVariableTypes;
288     delete[] piAllVariableIntegerTypes;
289     delete[] piAllVariableNbRows;
290     delete[] piAllVariableNbCols;
291 }
292
293 /*--------------------------------------------------------------------------*/
294 static std::set<string> createScilabDefaultVariablesSet()
295 {
296     string arr[] = { "home",
297                      "PWD",
298                      "%tk",
299                      "%pvm",
300                      "MSDOS",
301                      "%F",
302                      "%T",
303                      "%f",
304                      "%t",
305                      "%e",
306                      "%pi",
307                      "%modalWarning",
308                      "%nan",
309                      "%inf",
310                      "SCI",
311                      "WSCI",
312                      "SCIHOME",
313                      "TMPDIR",
314                      "%gui",
315                      "%fftw",
316                      "%helps",
317                      "%eps",
318                      "%io",
319                      "%i",
320                      "demolist",
321                      "%z",
322                      "%s",
323                      "$",
324                      "%toolboxes",
325                      "%toolboxes_dir",
326                      "TICTOC",
327                      "%helps_modules",
328                      "%_atoms_cache",
329                      "evoid", // Constant for external object
330                      "jvoid", // Constant for external object Java (jims)
331                      "jnull", // Constant for external object Java (jims)
332                      "enull"  // Constant for external object
333                    };
334     int i = 0;
335
336 #define NBELEMENT 37
337     std::set<string> ScilabDefaultVariables;
338
339     for (i = 0; i < NBELEMENT; i++)
340     {
341         ScilabDefaultVariables.insert(arr[i]);
342     }
343
344     return ScilabDefaultVariables;
345 }
346
347 static char * getListName(char * variableName)
348 {
349     SciErr sciErr;
350     int *piAddr = NULL;
351     int* piAddr1 = NULL;
352     int iRows = 0;
353     int iCols = 0;
354     char **pstType;
355     char *tmpChar;
356     sciErr = getVarAddressFromName(NULL, variableName, &piAddr);
357     if (sciErr.iErr)
358     {
359         return os_strdup("");
360     }
361
362     sciErr = getListItemAddress(NULL, piAddr, 1, &piAddr1);
363     if (sciErr.iErr)
364     {
365         return os_strdup("");
366     }
367
368     if (getAllocatedMatrixOfString(NULL, piAddr1, &iRows, &iCols, &pstType))
369     {
370
371         return os_strdup("");
372     }
373     tmpChar = os_strdup(pstType[0]);
374     freeAllocatedMatrixOfString(iRows, iCols, pstType);
375     return tmpChar;
376 }
377
378 static char *valueToDisplay(types::InternalType* pIT)
379 {
380     types::GenericType *pGT = pIT->getAs<types::GenericType>();
381     int *piDims = pGT->getDimsArray();
382
383     if (pIT->isDouble() && pGT->getDims() < 3 && pGT->getSize() <= 4) {
384         // 4 is the dimension max to which display the content
385         types::Double* pD = pIT->getAs<types::Double>();
386         // Small double value, display it
387         double* pdblReal = nullptr;
388         double* pdblImg = nullptr;
389         pdblReal = pD->get();
390
391         if (pD->isComplex())
392         {
393             pdblImg = pD->getImg();
394         }
395
396         return os_strdup(formatMatrix(piDims[0], piDims[1], pdblReal, pdblImg).c_str());
397     }
398     else
399     {
400         std::string sizeStr = std::to_string(piDims[0]);
401         for (int i = 1; i < pGT->getDims(); i++)
402         {
403             sizeStr.append("x");
404             sizeStr.append(std::to_string(piDims[i]));
405         }
406
407         return os_strdup(sizeStr.data());
408     }
409 }
410
411 std::string addDouble(double dbl)
412 {
413 #define PRECISION_DISPLAY 3
414     std::ostringstream os;
415     if (ISNAN(dbl))
416     {
417         os << NAN_STR;
418     }
419     else if (finite(dbl))
420     {
421         os.precision(PRECISION_DISPLAY);
422         os << dbl; // Convert the double to string
423     }
424     else
425     {
426         if (dbl > 0)
427         {
428             os << INF_STR;
429         }
430         else
431         {
432             os << NEG_INF_STR;
433         }
434     }
435
436     return os.str();
437 }
438 std::string formatMatrix(int nbRows, int nbCols, double *pdblReal, double *pdblImg)
439 {
440     int i, j ;
441     if (nbRows * nbCols == 1)
442     {
443         std::ostringstream os;
444         std::string formatted = addDouble(pdblReal[0]);
445         if (pdblImg)
446         {
447             double img = pdblImg[0];
448             if (img > 0)
449             {
450                 formatted += PLUS_STR;
451             }
452             else
453             {
454                 formatted += MINUS_STR;
455             }
456             formatted += addDouble(std::fabs(img));
457             formatted += I_STR;
458         }
459         return formatted;
460     }
461
462     std::string formatted = LBRACKET_STR;
463     for (j = 0 ; j < nbRows ; j++)
464     {
465         for (i = 0 ; i < nbCols ; i++)
466         {
467             /* Display the formatted matrix ... the way the user
468              * expect */
469             formatted += addDouble(pdblReal[i * nbRows + j]);
470             if (pdblImg)
471             {
472                 double img = pdblImg[i * nbRows + j];
473                 if (img > 0)
474                 {
475                     formatted += PLUS_STR;
476                 }
477                 else
478                 {
479                     formatted += MINUS_STR;
480                 }
481
482                 formatted += addDouble(std::fabs(img));
483                 formatted += I_STR;
484             }
485
486
487             if (i + 1 != nbCols) // Not the last element of the matrix
488             {
489                 formatted += COMMA_STR;
490             }
491         }
492         if (j + 1 != nbRows) // Not the last line of the matrix
493         {
494             formatted += SEMICOLON_STR;
495         }
496     }
497     return formatted + "]";
498 }