notify added.
[scilab.git] / scilab / modules / functions_manager / src / cpp / funcmanager.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
13 #ifdef _MSC_VER
14 #pragma warning(disable : 4996) //It's not beautifull but that works !
15 #endif
16
17
18 //#include <iostream>
19 #include <fstream>
20 //#include <sstream>
21
22 //XML API
23 #include <libxml/xpath.h>
24 #include <libxml/xmlreader.h>
25
26 #include "MALLOC.h"
27 #include "sci_mode.h"
28 #include "funcmanager.hxx"
29 #include "configvariable.hxx"
30 #include "module_declaration.hxx"
31 #include "parser.hxx"
32 #include "execvisitor.hxx"
33
34 extern "C"
35 {
36         #include "findfiles.h"
37 #ifndef _MSC_VER
38         #include "stricmp.h"
39 #endif
40 #include "os_strdup.h"
41 }
42
43
44
45 using namespace std;
46 using namespace ast;
47
48 #define BASENAMEMODULESFILE L"etc/modules.xml"
49
50 bool FileExist(std::string _szFile);
51 bool FileExist(std::wstring _szFile);
52 char *GetXmlFileEncoding(string _filename);
53
54 FuncManager::FuncManager(void)
55 {
56     m_bNoStart = false;
57 }
58
59 FuncManager::~FuncManager(void)
60 {
61 }
62
63 bool FuncManager::LoadModules(bool _bNoStart)
64 {
65     m_bNoStart = _bNoStart;
66         if(CreateModuleList() == false)
67     {
68         return false;
69     }
70
71         /*get module activation list from xml file*/
72         if(GetModules() == true)
73         {
74                 if(AppendModules() == false)
75         {
76             return false;
77         }
78         }
79
80     return LoadFuncByModule();
81 }
82
83 bool FuncManager::GetModules()
84 {
85         wstring szModulesFilename;
86
87         wstring szPath = ConfigVariable::getSCIPath();
88         if(szPath == L"")
89         {
90                 std::wcout << L"The SCI environment variable is not set." << std::endl;
91                 return false;
92         }
93
94         szModulesFilename = szPath + L"/";
95         szModulesFilename += BASENAMEMODULESFILE;
96
97         if(FileExist(szModulesFilename))
98         {
99                 m_szXmlFile = szModulesFilename;
100         }
101         else
102         {
103                 std::wcout << L"Cannot load the module declaration file: " << szModulesFilename << std::endl;
104                 return false;
105         }
106         return true;
107 }
108
109 bool FuncManager::AppendModules()
110 {
111     char* pstTemp = wide_string_to_UTF8(m_szXmlFile.c_str());
112
113         char *encoding=GetXmlFileEncoding(pstTemp);
114
115         /* Don't care about line return / empty line */
116         xmlKeepBlanksDefault(0);
117         /* check if the XML file has been encoded with utf8 (unicode) or not */
118         if(stricmp("utf-8", encoding)==0)
119         {
120                 xmlDocPtr doc;
121                 xmlXPathContextPtr xpathCtxt    = NULL;
122                 xmlXPathObjectPtr xpathObj              = NULL;
123                 char *name                                                                              = NULL;
124                 int activate                                                                    = 0;
125
126                 doc = xmlParseFile (pstTemp);
127
128                 if(doc == NULL)
129                 {
130                         std::cout << "Error: Could not parse file " << pstTemp << std::endl;
131                         if(encoding)
132                         {
133                                 free(encoding);
134                                 encoding=NULL;
135                         }
136             FREE(pstTemp);
137                         return false;
138                 }
139
140                 xpathCtxt = xmlXPathNewContext(doc);
141                 xpathObj = xmlXPathEval((const xmlChar*)"//modules/module", xpathCtxt);
142
143                 if(xpathObj && xpathObj->nodesetval->nodeMax)
144                 {
145                         /* the Xpath has been understood and there are node */
146                         for(int i = 0 ; i < xpathObj->nodesetval->nodeNr ; i++)
147                         {
148
149                                 xmlAttrPtr attrib = xpathObj->nodesetval->nodeTab[i]->properties;
150                                 /* Get the properties of <module>  */
151                                 while(attrib != NULL)
152                                 {
153                                         /* loop until when have read all the attributes */
154                                         if(xmlStrEqual (attrib->name, (const xmlChar*)"name"))
155                                         {
156                                                 /* we found the tag name */
157                                                 const char *str = (const char*)attrib->children->content;
158                                                 name = os_strdup(str);
159                                         }
160                                         else if(xmlStrEqual(attrib->name, (const xmlChar*)"activate"))
161                                         {
162                                                 /* we found the tag activate */
163                                                 const char *str = (const char*)attrib->children->content;
164                                                 if(stricmp(str,"yes") == 0 || strcmp(str,"1") == 0)
165                                                 {
166                                                         activate=1;
167                                                 }
168                                         }
169                                         attrib = attrib->next;
170                                 }
171
172                                 if((name) && (strlen(name) > 0) && (activate))
173                                 {
174                     wchar_t* pstName = to_wide_string(name);
175                                         if(VerifyModule(pstName))
176                                         {
177                                                 m_ModuleName.push_back(pstName);
178                     }
179                                         else
180                                         {
181                                                 std::wcout << pstName << " module not found." << std::endl;
182                                         }
183                     FREE(pstName);
184                                 }
185
186                                 if(name)
187                                 {
188                                         free(name);
189                                         name = NULL;
190                                 }
191                                 activate = 0;
192                         }
193                 }
194
195                 if(xpathObj) xmlXPathFreeObject(xpathObj);
196                 if(xpathCtxt) xmlXPathFreeContext(xpathCtxt);
197                 xmlFreeDoc (doc);
198         }
199         else
200         {
201                 std::cout << "Error: Not a valid module file " << pstTemp << " (encoding not 'utf-8') Encoding '" << encoding << "' found." << std::endl;
202         }
203         if (encoding)
204         {
205                 free(encoding);
206                 encoding = NULL;
207         }
208
209     ConfigVariable::setModuleList(m_ModuleName);
210     FREE(pstTemp);
211
212         return true;
213 }
214
215 bool FuncManager::VerifyModule(wchar_t* _pszModuleName)
216 {
217         wstring SciPath = ConfigVariable::getSCIPath();
218         if(SciPath == L"")
219         {
220                 std::wcout << L"The SCI environment variable is not set." << std::endl;
221                 return false;
222         }
223
224         wstring FullPathModuleName = SciPath + L"/modules/" + _pszModuleName + L"/etc/" + _pszModuleName + START_EXT;
225
226         /* ajouter d'autres tests d'existences */
227
228         if(!FileExist(FullPathModuleName))
229         {
230                 return false;
231         }
232         return true;
233 }
234
235 /*Out of class*/
236 bool FileExist(std::string _szFile)
237 {
238         bool bReturn = false;
239         fstream filestr(_szFile.c_str(), fstream::in);
240         bReturn = !filestr.fail();
241         filestr.close();
242         return bReturn;
243 }
244
245 bool FileExist(std::wstring _szFile)
246 {
247         bool bReturn = false;
248     char *pstFile = wide_string_to_UTF8(_szFile.c_str());
249         wfstream filestr(pstFile, wfstream::in);
250         bReturn = !filestr.fail();
251         filestr.close();
252     FREE(pstFile);
253         return bReturn;
254 }
255
256 char *GetXmlFileEncoding(string _filename)
257 {
258 #define DEFAULT_ENCODING "UTF-8"
259
260         char *encoding = NULL;
261         xmlDocPtr doc = NULL;
262
263         /* default */
264         encoding = os_strdup(DEFAULT_ENCODING);
265
266         doc = xmlParseFile(_filename.c_str());
267         if (doc)
268         {
269                 if (doc->encoding)
270                 {
271                         if(encoding)
272                         {
273                                 free(encoding);
274                                 encoding = NULL;
275                         }
276                         encoding = os_strdup((char*)doc->encoding);
277                 }
278         }
279
280         xmlFreeDoc(doc);
281         return encoding;
282 }
283
284 bool FuncManager::CreateModuleList(void)
285 {
286     m_ModuleMap.insert(pair<wstring, GW_MOD>(L"elementary_functions", &ElemFuncModule::Load));
287     m_ModuleMap.insert(pair<wstring, GW_MOD>(L"types", &TypesModule::Load));
288     m_ModuleMap.insert(pair<wstring, GW_MOD>(L"boolean", &BooleanModule::Load));
289     m_ModuleMap.insert(pair<wstring, GW_MOD>(L"integer", &IntegerModule::Load));
290     m_ModuleMap.insert(pair<wstring, GW_MOD>(L"core", &CoreModule::Load));
291     m_ModuleMap.insert(pair<wstring, GW_MOD>(L"io", &IoModule::Load));
292     m_ModuleMap.insert(pair<wstring, GW_MOD>(L"functions", &FunctionsModule::Load));
293     m_ModuleMap.insert(pair<wstring, GW_MOD>(L"output_stream", &OutputStreamModule::Load));
294     m_ModuleMap.insert(pair<wstring, GW_MOD>(L"matio", &MatioModule::Load));
295     m_ModuleMap.insert(pair<wstring, GW_MOD>(L"fileio", &FileioModule::Load));
296     m_ModuleMap.insert(pair<wstring, GW_MOD>(L"gui", &GuiModule::Load));
297     m_ModuleMap.insert(pair<wstring, GW_MOD>(L"time", &TimeModule::Load));
298     m_ModuleMap.insert(pair<wstring, GW_MOD>(L"string", &StringModule::Load));
299     m_ModuleMap.insert(pair<wstring, GW_MOD>(L"scinotes", &ScinotesModule::Load));
300     m_ModuleMap.insert(pair<wstring, GW_MOD>(L"localization", &LocalizationModule::Load));
301     m_ModuleMap.insert(pair<wstring, GW_MOD>(L"helptools", &HelptoolsModule::Load));
302     m_ModuleMap.insert(pair<wstring, GW_MOD>(L"hdf5", &Hdf5Module::Load));
303     m_ModuleMap.insert(pair<wstring, GW_MOD>(L"dynamic_link", &DynamicLinkModule::Load));
304     m_ModuleMap.insert(pair<wstring, GW_MOD>(L"action_binding", &ActionBindingModule::Load));
305     if (ConfigVariable::getScilabMode() != SCILAB_NWNI)
306     {
307         m_ModuleMap.insert(pair<wstring, GW_MOD>(L"jvm", &JvmModule::Load));
308     }
309 #ifdef _MSC_VER
310     m_ModuleMap.insert(pair<wstring, GW_MOD>(L"windows_tools", &WindowsToolsModule::Load));
311 #endif
312     return true;
313 }
314
315 bool FuncManager::LoadFuncByModule(void)
316 {
317         bool bRet       = true;
318         list<wstring>::const_iterator itName;
319
320     //load gateways
321         for(itName = m_ModuleName.begin() ; itName != m_ModuleName.end() ; itName++)
322         {
323         std::map<wstring, GW_MOD>::iterator itModule = m_ModuleMap.find(*itName);
324                 if(itModule != m_ModuleMap.end())
325                 {
326             //check if module have gateways
327             if(itModule->second != NULL)
328             {
329                 //call ::Load function
330                 itModule->second();
331             }
332                 }
333         }
334
335     if(m_bNoStart == false)
336     {
337         //excute .start file
338             for(itName = m_ModuleName.begin() ; itName != m_ModuleName.end() ; itName++)
339             {
340                     ExecuteStartFile(*itName);
341             }
342     }
343
344         return bRet;
345 }
346
347 bool FuncManager::ExecuteStartFile(wstring _stModule)
348 {
349     //build .start filename
350         wstring stPath = ConfigVariable::getSCIPath();
351         stPath += MODULE_DIR;
352         stPath += _stModule;
353         stPath += ETC_DIR;
354         stPath += _stModule;
355         stPath += START_EXT;
356
357     Parser parser;
358
359     parser.parseFile(stPath, ConfigVariable::getSCIPath());
360
361     if(parser.getExitStatus() == Parser::Failed)
362     {
363         std::wostringstream ostr;
364         ostr << _W("Unable to execute : ") << stPath << endl;
365         YaspWriteW(ostr.str().c_str());
366         delete parser.getTree();
367         return false;
368     }
369
370     ExecVisitor execStart;
371
372     //save current prompt mode
373     int oldVal = ConfigVariable::getPromptMode();
374     //set mode silent for errors
375     ConfigVariable::setPromptMode(-1);
376     try
377     {
378         parser.getTree()->accept(execStart);
379
380     }
381     catch(ast::ScilabMessage sm)
382     {
383         YaspWriteW(sm.GetErrorMessage().c_str());
384     }
385     catch(ast::ScilabError se)
386     {
387         YaspWriteW(se.GetErrorMessage().c_str());
388     }
389
390     //restore previous prompt mode
391     ConfigVariable::setPromptMode(oldVal);
392     delete parser.getTree();
393     return true;
394 }