add function libraryinfo and librarieslist
[scilab.git] / scilab / modules / ast / src / cpp / symbol / context.cpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2008-2008 - DIGITEO - 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 #include <iomanip>
13 #include <cctype>
14
15 #include "context.hxx"
16 #include "internal.hxx"
17 #include "function.hxx"
18 #include "macro.hxx"
19 #include "macrofile.hxx"
20 #include "variables.hxx"
21 #include "configvariable.hxx"
22
23 extern "C"
24 {
25 #include "getmemory.h"
26 #include "os_string.h"
27 }
28
29 namespace symbol
30 {
31 Context* Context::me;
32
33 Context::Context()
34 {
35     m_iLevel = 0;
36     varStack.push(new VarList());
37     globals = new std::list<Symbol>();
38 }
39
40 Context::~Context()
41 {
42     while (!varStack.empty())
43     {
44         VarList * pVL = varStack.top();
45         pVL->clear();
46         delete pVL;
47         varStack.pop();
48     }
49     if (globals)
50     {
51         delete globals;
52     }
53 }
54
55 Context* Context::getInstance(void)
56 {
57     if (me == 0)
58     {
59         me = new Context();
60     }
61     return me;
62 }
63
64 void Context::destroyInstance(void)
65 {
66     if (me)
67     {
68         delete me;
69     }
70 }
71
72 void Context::scope_begin()
73 {
74     m_iLevel++;
75     varStack.push(new VarList());
76 }
77
78 void Context::clearAll()
79 {
80     libraries.clearAll();
81     variables.clearAll();
82 }
83
84 void Context::scope_end()
85 {
86     //clear varList of current scope
87     if (varStack.empty() == false)
88     {
89         clearCurrentScope(true);
90     }
91
92     m_iLevel--;
93 }
94
95 bool Context::clearCurrentScope(bool _bClose)
96 {
97     if (varStack.empty())
98     {
99         return true;
100     }
101
102     VarList* varList = varStack.top();
103     std::map<Symbol, Variable*>::iterator it = varList->begin();
104     for (; it != varList->end() ; ++it)
105     {
106         if (it->second->empty() == false && it->second->top()->m_iLevel == m_iLevel)
107         {
108             ScopedVariable * pSV = it->second->top();
109             types::InternalType * pIT = pSV->m_pIT;
110             pIT->DecreaseRef();
111             pIT->killMe();
112             it->second->pop();
113             delete pSV;
114         }
115     }
116
117     varList->clear();
118
119     if (_bClose)
120     {
121         delete varList;
122         varStack.pop();
123     }
124
125     return true;
126 }
127
128 Variable* Context::getOrCreate(const Symbol& _key)
129 {
130     return variables.getOrCreate(_key);
131 }
132
133 types::InternalType* Context::get(const Symbol& _key)
134 {
135     return get(_key, -1);
136 }
137
138 types::InternalType* Context::get(const Variable* _var)
139 {
140     types::InternalType* pIT = _var->get();
141     if (pIT == NULL)
142     {
143         //look in libraries
144         pIT = libraries.get(_var->getSymbol(), -1);
145         if (pIT && pIT->isLibrary() == false)
146         {
147             put((Variable*)_var, pIT);
148         }
149     }
150
151     return pIT;
152 }
153
154 types::InternalType* Context::get(const Symbol& _key, int _iLevel)
155 {
156     types::InternalType* pIT = NULL;
157     if (_iLevel == m_iLevel || _iLevel == -1)
158     {
159         //look for in current VarList
160         VarList::iterator it = varStack.top()->find(_key);
161         if (it != varStack.top()->end())
162         {
163             if (it->second->empty() == false)
164             {
165                 return it->second->top()->m_pIT;
166             }
167         }
168     }
169
170     if (pIT == NULL)
171     {
172         pIT = variables.get(_key, _iLevel);
173         if (pIT == NULL)
174         {
175             //find in libraries
176             pIT = libraries.get(_key, _iLevel);
177         }
178     }
179
180     return pIT;
181 }
182
183 types::InternalType* Context::getCurrentLevel(const Symbol& _key)
184 {
185     return variables.get(_key, m_iLevel);
186 }
187
188 types::InternalType* Context::getAllButCurrentLevel(const Symbol& _key)
189 {
190     return variables.getAllButCurrentLevel(_key, m_iLevel);
191 }
192
193 types::InternalType* Context::getFunction(const Symbol& _key)
194 {
195     return get(_key);
196 }
197
198 std::list<Symbol>* Context::getFunctionList(std::wstring _stModuleName)
199 {
200     return variables.getFunctionList(_stModuleName, m_iLevel);
201 }
202
203 std::list<std::wstring>* Context::getVarsName()
204 {
205     std::list<std::wstring>* vars = variables.getVarsName();
206     std::list<std::wstring>* libs = libraries.getVarsName();
207     vars->insert(vars->end(), libs->begin(), libs->end());
208     delete libs;
209
210     for (auto it = globals->begin(), itEnd = globals->end(); it != itEnd; ++it)
211     {
212         vars->push_back((*it).getName());
213     }
214     return vars;
215 }
216
217 std::list<std::wstring>* Context::getMacrosName()
218 {
219     std::list<std::wstring>* vars = variables.getMacrosName();
220     std::list<std::wstring>* libs = libraries.getMacrosName();
221     vars->insert(vars->end(), libs->begin(), libs->end());
222     delete libs;
223     return vars;
224 }
225
226 std::list<std::wstring>* Context::getFunctionsName()
227 {
228     return variables.getFunctionsName();
229 }
230
231 std::list<std::wstring>* Context::getVarsNameForWho(bool bSorted)
232 {
233     std::list<std::wstring>* lstVar = new std::list<std::wstring>();
234     int iZero = 0;
235     variables.getVarsNameForWho(lstVar, &iZero, NULL, &iZero, bSorted);
236     return lstVar;
237 }
238
239 std::list<std::wstring>* Context::getGlobalNameForWho(bool bSorted)
240 {
241     std::list<std::wstring>* lstVar = new std::list<std::wstring>();
242     int iZero = 0;
243     variables.getVarsNameForWho(NULL, &iZero, lstVar, &iZero, bSorted);
244     return lstVar;
245 }
246
247 std::list<std::wstring>* Context::getWhereIs(const std::wstring& _str)
248 {
249     return libraries.whereis(Symbol(_str));
250 }
251
252 std::list<std::wstring>* Context::getLibrariesList()
253 {
254     return libraries.librarieslist();
255 }
256
257 void Context::put(Variable* _var, types::InternalType* _pIT)
258 {
259     if (_pIT->isLibrary())
260     {
261         Library* lib = libraries.getOrCreate(_var->getSymbol());
262         lib->put((types::Library*)_pIT, m_iLevel);
263     }
264     else
265     {
266         _var->put(_pIT, m_iLevel);
267         if (varStack.empty() == false)
268         {
269             (*varStack.top())[_var->getSymbol()] = _var;
270         }
271     }
272 }
273
274 void Context::put(const Symbol& _key, types::InternalType* _pIT)
275 {
276     Variable* var = variables.getOrCreate(_key);
277     put(var, _pIT);
278 }
279
280 bool Context::remove(const Symbol& _key)
281 {
282     bool ret = variables.remove(_key, m_iLevel);
283
284     if (ret)
285     {
286         varStack.top()->erase(_key);
287     }
288
289     ret = ret | libraries.remove(_key, m_iLevel);
290     return ret;
291 }
292
293 bool Context::removeAll()
294 {
295     return clearCurrentScope(false);
296 }
297
298 bool Context::putInPreviousScope(Variable* _var, types::InternalType* _pIT)
299 {
300     //add variable in previous scope
301     variables.putInPreviousScope(_var, _pIT, m_iLevel - 1);
302
303     //add variable in stack of using variables
304     if (varStack.empty() == false)
305     {
306         VarList * list = varStack.top();
307         varStack.pop();
308         if (varStack.empty() == false)
309         {
310             (*varStack.top())[_var->getSymbol()] = _var;
311             varStack.push(list);
312         }
313     }
314     return true;
315 }
316
317 bool Context::addFunction(types::Function *_info)
318 {
319     Variable* var = variables.getOrCreate(Symbol(_info->getName()));
320     variables.putInPreviousScope(var, _info, 0);
321     return true;
322 }
323
324 bool Context::addMacro(types::Macro *_info)
325 {
326     put(Symbol(_info->getName()), _info);
327     return true;
328 }
329
330 bool Context::addMacroFile(types::MacroFile *_info)
331 {
332     put(Symbol(_info->getName()), _info);
333     return true;
334 }
335
336 bool Context::isGlobalVisible(const Symbol& _key)
337 {
338     return variables.isGlobalVisible(_key, m_iLevel);
339 }
340
341 /*return global variable existance status*/
342 bool Context::isGlobal(const Symbol& _key)
343 {
344     return variables.isGlobal(_key, m_iLevel);
345 }
346
347 types::InternalType* Context::getGlobalValue(const Symbol& _key)
348 {
349     return variables.getGlobalValue(_key);
350 }
351
352 void Context::setGlobalVisible(const Symbol& _key, bool bVisible)
353 {
354     variables.setGlobalVisible(_key, bVisible, m_iLevel);
355 }
356
357 void Context::setGlobal(const Symbol& _key)
358 {
359     variables.setGlobal(_key);
360     globals->push_back(_key);
361 }
362
363 void Context::removeGlobal(const Symbol& _key)
364 {
365     variables.removeGlobal(_key, m_iLevel);
366     globals->remove(_key);
367 }
368
369 void Context::removeGlobalAll()
370 {
371     std::list<Symbol>::iterator it = globals->begin();
372     while (it != globals->end())
373     {
374         removeGlobal(*it);
375         it = globals->begin();
376     }
377
378     globals->clear();
379 }
380
381 void Context::print(std::wostream& ostr, bool sorted) const
382 {
383     std::list<std::wstring> lstVar;
384     std::list<std::wstring> lstGlobal;
385     int iVarLenMax = 10; // initialise to the minimal value of padding
386     int iGlobalLenMax = 10; // initialise to the minimal value of padding
387     variables.getVarsNameForWho(&lstVar, &iVarLenMax, &lstGlobal, &iGlobalLenMax);
388     libraries.getVarsNameForWho(&lstVar, &iVarLenMax);
389
390     if (sorted)
391     {
392         lstVar.sort();
393         lstGlobal.sort();
394     }
395
396 #define strSize 64
397     wchar_t wcsVarElem[strSize];
398     wchar_t wcsVarVariable[strSize];
399     wchar_t wcsGlobalElem[strSize];
400     wchar_t wcsGlobalVariable[strSize];
401
402     int iMemTotal = 0;
403     int iMemUsed  = 0;
404     int nbMaxVar  = 0;
405
406 #ifdef _MSC_VER
407     MEMORYSTATUSEX statex;
408     statex.dwLength = sizeof(statex);
409     GlobalMemoryStatusEx (&statex);
410     iMemTotal = (int)(statex.ullTotalPhys / (1024 * 1024));
411 #else
412     iMemTotal = getmemorysize();
413 #endif
414
415     ostr << _W("Your variables are:") << std::endl << std::endl;
416     std::list<std::wstring>::const_iterator it = lstVar.begin();
417     int iWidth = ConfigVariable::getConsoleWidth();
418     int iCurrentWidth = 0;
419     for (int i = 1; it != lstVar.end(); ++it, i++)
420     {
421         if (iCurrentWidth + iVarLenMax + 1 > iWidth)
422         {
423             ostr << std::endl;
424             iCurrentWidth = 0;
425         }
426         ostr << std::setw(iVarLenMax + 1) << *it;
427         iCurrentWidth += iVarLenMax + 1;
428     }
429
430     os_swprintf(wcsVarElem, strSize, _W(" using %10d elements out of  %10d.\n").c_str(), iMemUsed, iMemTotal);
431     ostr << std::endl << wcsVarElem;
432
433     os_swprintf(wcsVarVariable, strSize, _W(" and   %10d variables out of %10d.\n").c_str(), lstVar.size(), nbMaxVar);
434     ostr << wcsVarVariable << std::endl;
435
436     ostr << std::endl << _W("Your global variables are:") << std::endl << std::endl;
437     it = lstGlobal.begin();
438     for (int i = 1; it != lstGlobal.end(); ++it, i++)
439     {
440         ostr << std::setw(iGlobalLenMax + 1) << *it;
441         if (i % 4 == 0)
442         {
443             ostr << std::endl;
444         }
445     }
446
447     ostr << std::endl;
448
449     os_swprintf(wcsGlobalElem, strSize, _W(" using %10d elements out of  %10d.\n").c_str(), iMemUsed, iMemTotal);
450     ostr << std::endl << wcsGlobalElem;
451
452     os_swprintf(wcsGlobalVariable, strSize, _W(" and   %10d variables out of %10d.\n").c_str(), lstGlobal.size(), nbMaxVar);
453     ostr << wcsGlobalVariable;
454 }
455
456 int Context::getScopeLevel()
457 {
458     return m_iLevel;
459 }
460
461 bool Context::isValidVariableName(const wchar_t* wcsVarName)
462 {
463     static const wchar_t FORBIDDEN_CHARS[] = L" */\\.,;:^@><=+-&|()~\n\t'\"";
464     if (wcslen(wcsVarName) == 0 || std::wcspbrk(wcsVarName, FORBIDDEN_CHARS) || isdigit(wcsVarName[0]))
465     {
466         return false;
467     }
468     return true;
469 }
470
471 bool Context::isValidVariableName(const char* name)
472 {
473     bool isValid = false;
474     wchar_t* wcsname = to_wide_string(name);
475     if (wcsname)
476     {
477         isValid = isValidVariableName(wcsname);
478         FREE(wcsname);
479     }
480
481     return isValid;
482 }
483 }