2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2008-2008 - DIGITEO - Antoine ELIAS
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
15 #include "context.hxx"
16 #include "internal.hxx"
17 #include "function.hxx"
19 #include "macrofile.hxx"
20 #include "variables.hxx"
21 #include "configvariable.hxx"
25 #include "getmemory.h"
26 #include "os_string.h"
36 varStack.push(new VarList());
37 globals = new std::list<Symbol>();
42 while (!varStack.empty())
44 VarList * pVL = varStack.top();
55 Context* Context::getInstance(void)
64 void Context::destroyInstance(void)
72 void Context::scope_begin()
75 varStack.push(new VarList());
78 void Context::clearAll()
84 void Context::scope_end()
86 //clear varList of current scope
87 if (varStack.empty() == false)
89 clearCurrentScope(true);
95 bool Context::clearCurrentScope(bool _bClose)
102 VarList* varList = varStack.top();
103 std::list<Symbol> toremove;
104 for (auto var : *varList)
106 if (var.second->empty() == false)
108 ScopedVariable* pSV = var.second->top();
109 if (pSV->m_iLevel == m_iLevel && (_bClose || pSV->protect == false))
111 types::InternalType * pIT = pSV->m_pIT;
112 if (pIT->isLibrary())
114 // at scilab exit, pIT have a ref == 2 because
115 // it is contains in libraries and variables.
116 // call remove will set ref to 1 then the next
117 // pIT->DecreaseRef(); pIT->killMe(); will delete it.
118 libraries.remove(var.first, m_iLevel);
126 toremove.push_back(var.first);
138 for (auto var : toremove)
146 Variable* Context::getOrCreate(const Symbol& _key)
148 return variables.getOrCreate(_key);
151 types::InternalType* Context::get(const Symbol& _key)
153 return get(_key, -1);
156 types::InternalType* Context::get(const Variable* _var)
158 types::InternalType* pIT = _var->get();
162 pIT = libraries.get(_var->getSymbol(), -1);
163 if (pIT && pIT->isLibrary() == false)
165 put((Variable*)_var, pIT);
172 types::InternalType* Context::get(const Symbol& _key, int _iLevel)
174 types::InternalType* pIT = NULL;
175 if (_iLevel == m_iLevel || _iLevel == -1)
177 //look for in current VarList
178 VarList::iterator it = varStack.top()->find(_key);
179 if (it != varStack.top()->end())
181 if (it->second->empty() == false)
183 pIT = it->second->get();
190 pIT = variables.get(_key, _iLevel);
194 pIT = libraries.get(_key, _iLevel);
200 types::InternalType* Context::getCurrentLevel(const Symbol& _key)
202 return variables.get(_key, m_iLevel);
205 types::InternalType* Context::getCurrentLevel(Variable* _var)
207 return variables.get(_var, m_iLevel);
210 types::InternalType* Context::getAllButCurrentLevel(const Symbol& _key)
212 return variables.getAllButCurrentLevel(_key, m_iLevel);
215 types::InternalType* Context::getFunction(const Symbol& _key)
220 int Context::getFunctionList(std::list<Symbol>& lst, std::wstring _stModuleName)
222 return variables.getFunctionList(lst, _stModuleName, m_iLevel);
225 int Context::getVarsName(std::list<std::wstring>& lst)
227 variables.getVarsName(lst);
228 libraries.getVarsName(lst);
230 return static_cast<int>(lst.size());
233 int Context::getMacrosName(std::list<std::wstring>& lst)
235 variables.getMacrosName(lst);
236 libraries.getMacrosName(lst);
237 return static_cast<int>(lst.size());
240 int Context::getFunctionsName(std::list<std::wstring>& lst)
242 return variables.getFunctionsName(lst);
245 int Context::getVarsNameForWho(std::list<std::wstring>& lst, bool bSorted)
248 variables.getVarsNameForWho(lst, &iZero, bSorted);
249 return static_cast<int>(lst.size());
252 int Context::getGlobalNameForWho(std::list<std::wstring>& lst, bool bSorted)
255 variables.getGlobalNameForWho(lst, &iZero, bSorted);
256 return static_cast<int>(lst.size());
259 int Context::getWhereIs(std::list<std::wstring>& lst, const std::wstring& _str)
261 return libraries.whereis(lst, Symbol(_str));
264 int Context::getLibrariesList(std::list<std::wstring>& lst)
266 return libraries.librarieslist(lst);
269 void Context::put(Variable* _var, types::InternalType* _pIT)
271 if (_pIT->isLibrary())
273 Library* lib = libraries.getOrCreate(_var->getSymbol());
274 lib->put((types::Library*)_pIT, m_iLevel);
277 _var->put(_pIT, m_iLevel);
278 if (varStack.empty() == false)
280 (*varStack.top())[_var->getSymbol()] = _var;
284 void Context::put(const Symbol& _key, types::InternalType* _pIT)
286 Variable* var = variables.getOrCreate(_key);
290 bool Context::remove(const Symbol& _key)
292 bool ret = variables.remove(_key, m_iLevel);
296 varStack.top()->erase(_key);
299 ret = ret | libraries.remove(_key, m_iLevel);
303 bool Context::removeAll()
305 return clearCurrentScope(false);
308 bool Context::putInPreviousScope(Variable* _var, types::InternalType* _pIT)
310 //add variable in previous scope
311 variables.putInPreviousScope(_var, _pIT, m_iLevel - 1);
313 //add variable in stack of using variables
314 if (varStack.empty() == false)
316 VarList * list = varStack.top();
318 if (varStack.empty() == false)
320 (*varStack.top())[_var->getSymbol()] = _var;
325 if (_pIT->isLibrary())
327 libraries.putInPreviousScope(_var->getSymbol(), _pIT->getAs<types::Library>(), m_iLevel - 1);
332 bool Context::addFunction(types::Function *_info)
334 Variable* var = variables.getOrCreate(Symbol(_info->getName()));
335 variables.putInPreviousScope(var, _info, 0);
339 bool Context::addMacro(types::Macro *_info)
341 put(Symbol(_info->getName()), _info);
345 bool Context::addMacroFile(types::MacroFile *_info)
347 put(Symbol(_info->getName()), _info);
351 bool Context::isGlobalVisible(const Symbol& _key)
353 return variables.isGlobalVisible(_key, m_iLevel);
356 /*return global variable existance status*/
357 bool Context::isGlobal(const Symbol& _key)
359 return variables.isGlobal(_key, m_iLevel);
362 types::InternalType* Context::getGlobalValue(const Symbol& _key)
364 return variables.getGlobalValue(_key);
367 void Context::setGlobalVisible(const Symbol& _key, bool bVisible)
369 variables.setGlobalVisible(_key, bVisible, m_iLevel);
372 void Context::setGlobal(const Symbol& _key)
374 variables.setGlobal(_key);
375 globals->push_back(_key);
378 void Context::removeGlobal(const Symbol& _key)
380 variables.removeGlobal(_key, m_iLevel);
381 globals->remove(_key);
384 void Context::removeGlobalAll()
386 std::list<Symbol>::iterator it = globals->begin();
387 while (it != globals->end())
390 it = globals->begin();
396 void Context::print(std::wostream& ostr, bool sorted) const
398 std::list<std::wstring> lstVar;
399 std::list<std::wstring> lstGlobal;
400 int iVarLenMax = 10; // initialise to the minimal value of padding
401 int iGlobalLenMax = 10; // initialise to the minimal value of padding
402 variables.getVarsNameForWho(lstVar, &iVarLenMax);
403 variables.getGlobalNameForWho(lstGlobal, &iGlobalLenMax);
404 libraries.getVarsNameForWho(&lstVar, &iVarLenMax);
413 wchar_t wcsVarElem[strSize];
414 wchar_t wcsVarVariable[strSize];
415 wchar_t wcsGlobalElem[strSize];
416 wchar_t wcsGlobalVariable[strSize];
423 MEMORYSTATUSEX statex;
424 statex.dwLength = sizeof(statex);
425 GlobalMemoryStatusEx(&statex);
426 iMemTotal = (int)(statex.ullTotalPhys / (1024 * 1024));
428 iMemTotal = getmemorysize();
431 ostr << _W("Your variables are:") << std::endl << std::endl;
432 std::list<std::wstring>::const_iterator it = lstVar.begin();
433 int iWidth = ConfigVariable::getConsoleWidth();
434 int iCurrentWidth = 0;
435 for (int i = 1; it != lstVar.end(); ++it, i++)
437 if (iCurrentWidth + iVarLenMax + 1 > iWidth)
442 ostr << std::setw(iVarLenMax + 1) << *it;
443 iCurrentWidth += iVarLenMax + 1;
446 os_swprintf(wcsVarElem, strSize, _W(" using %10d elements out of %10d.\n").c_str(), iMemUsed, iMemTotal);
447 ostr << std::endl << wcsVarElem;
449 os_swprintf(wcsVarVariable, strSize, _W(" and %10d variables out of %10d.\n").c_str(), lstVar.size(), nbMaxVar);
450 ostr << wcsVarVariable << std::endl;
452 ostr << std::endl << _W("Your global variables are:") << std::endl << std::endl;
453 it = lstGlobal.begin();
454 for (int i = 1; it != lstGlobal.end(); ++it, i++)
456 ostr << std::setw(iGlobalLenMax + 1) << *it;
465 os_swprintf(wcsGlobalElem, strSize, _W(" using %10d elements out of %10d.\n").c_str(), iMemUsed, iMemTotal);
466 ostr << std::endl << wcsGlobalElem;
468 os_swprintf(wcsGlobalVariable, strSize, _W(" and %10d variables out of %10d.\n").c_str(), lstGlobal.size(), nbMaxVar);
469 ostr << wcsGlobalVariable;
472 int Context::getScopeLevel()
477 bool Context::isValidVariableName(const wchar_t* wcsVarName)
479 static const wchar_t FORBIDDEN_CHARS[] = L" */\\.,;:^@><=+-&|()~\n\t'\"";
480 if (wcslen(wcsVarName) == 0 || std::wcspbrk(wcsVarName, FORBIDDEN_CHARS) || isdigit(wcsVarName[0]))
487 bool Context::isValidVariableName(const char* name)
489 bool isValid = false;
490 wchar_t* wcsname = to_wide_string(name);
493 isValid = isValidVariableName(wcsname);
500 int Context::getLibsToVariableBrowser(std::list<Library*>& lst)
502 libraries.getVarsToVariableBrowser(lst);
504 std::list<Library*> toremove;
505 //list lib that have a variable with the same name
508 Variable* var = getOrCreate(lib->getSymbol());
509 if (var->empty() == false)
511 toremove.push_back(lib);
516 for (auto lib : toremove)
521 return static_cast<int>(lst.size());
524 int Context::getVarsToVariableBrowser(std::list<Variable*>& lst)
526 variables.getVarsToVariableBrowser(lst);
527 return static_cast<int>(lst.size());
530 void Context::updateProtection(bool protect)
532 if (varStack.empty() == false)
534 VarList* lst = varStack.top();
535 for (auto var : *lst)
537 if (var.second->empty() == false)
539 ScopedVariable* pSV = var.second->top();
540 //only for current scope but normally vars in VarStack are in the current scope
541 if (pSV->m_iLevel == m_iLevel)
543 pSV->protect = protect;
547 std::wcerr << L"heu ... " << var.first.getName() << std::endl;
554 void Context::protect()
556 updateProtection(true);
559 void Context::unprotect()
561 updateProtection(false);
564 bool Context::isprotected(const Symbol& key)
566 return isprotected(getOrCreate(key));
569 bool Context::isprotected(Variable* _var)
571 //don't check protection on "ans"
572 if (_var->getSymbol().getName() == L"ans")
577 if (_var->empty() == false)
579 ScopedVariable* pSV = _var->top();
580 if (pSV->m_iLevel == m_iLevel && pSV->protect)
588 int Context::protectedVars(std::list<std::wstring>& vars)
590 return variables.getProtectedVarsName(vars);