memory leak fixed in library management.
[scilab.git] / scilab / modules / io / src / cpp / loadlib.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2014 - Scilab Enterprises - 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 #include "configvariable.hxx"
14 #include "context.hxx"
15 #include "loadlib.hxx"
16 #include "macrofile.hxx"
17
18 extern "C"
19 {
20 #include "sci_malloc.h"
21 #include "os_string.h"
22 #include "expandPathVariable.h"
23 #include "PATH_MAX.h"
24 #include <libxml/xpath.h>
25 #include <libxml/xmlreader.h>
26 }
27
28 #define DEFAULT_ENCODING "UTF-8"
29
30 static char *GetXmlFileEncoding(std::string _filename);
31
32 types::Library* loadlib(std::wstring _wstXML, bool _isFile, bool _bAddInContext)
33 {
34     types::Library* lib = NULL;
35
36     wchar_t* pwstPathLib = expandPathVariableW((wchar_t*)_wstXML.c_str());
37
38     std::wstring wstOriginalPath(_wstXML);
39     std::wstring wstFile(pwstPathLib);
40     std::wstring wstPath(pwstPathLib);
41     FREE(pwstPathLib);
42
43     if (_isFile)
44     {
45         size_t pos = wstPath.find_last_of(L"/\\");
46         wstPath = wstPath.substr(0, pos);
47         pos = wstOriginalPath.find_last_of(L"/\\");
48         wstOriginalPath = wstOriginalPath.substr(0, pos + 1); //with ending /
49     }
50     else
51     {
52         if (wstFile.empty() == false && *wstFile.rbegin() != DIR_SEPARATORW[0])
53         {
54             wstFile += DIR_SEPARATORW;
55         }
56
57         wstFile += L"lib";
58     }
59
60     char* pstFile = wide_string_to_UTF8(wstFile.c_str());
61     char *encoding = GetXmlFileEncoding(pstFile);
62
63     /* Don't care about line return / empty line */
64     xmlKeepBlanksDefault(0);
65     /* check if the XML file has been encoded with utf8 (unicode) or not */
66     if (stricmp("utf-8", encoding))
67     {
68         std::wcout << "Error: Not a valid module file " << pstFile << " (encoding not 'utf-8') Encoding '" << encoding << "' found." << std::endl;
69         FREE(pstFile);
70         free(encoding);
71         return NULL;
72     }
73
74     xmlDocPtr doc;
75     xmlXPathContextPtr xpathCtxt    = NULL;
76     xmlXPathObjectPtr xpathObj      = NULL;
77     wchar_t* pstName                = NULL;
78     wchar_t* pstLibName             = NULL;
79     wchar_t* pstFileName            = NULL;
80
81     free(encoding);
82
83     doc = xmlParseFile(pstFile);
84
85     if (doc == NULL)
86     {
87         std::cout << "Error: Could not parse file " << pstFile << std::endl;
88         FREE(pstFile);
89         return NULL;
90     }
91
92     FREE(pstFile);
93
94     lib = new types::Library(wstOriginalPath);
95
96     xpathCtxt = xmlXPathNewContext(doc);
97     xpathObj = xmlXPathEval((const xmlChar*)"//scilablib", xpathCtxt);
98     if (xpathObj && xpathObj->nodesetval->nodeMax)
99     {
100         xmlAttrPtr attrib = xpathObj->nodesetval->nodeTab[0]->properties;
101         if (xmlStrEqual (attrib->name, (const xmlChar*)"name"))
102         {
103             /* we found the tag name */
104             const char *str = (const char*)attrib->children->content;
105             pstLibName = to_wide_string(str);
106             xmlXPathFreeObject(xpathObj);
107         }
108         else
109         {
110             if (xpathCtxt)
111             {
112                 xmlXPathFreeContext(xpathCtxt);
113             }
114             xmlXPathFreeObject(xpathObj);
115             delete lib;
116             return NULL;
117         }
118     }
119
120     xpathObj = xmlXPathEval((const xmlChar*)"//scilablib/macro", xpathCtxt);
121     if (xpathObj && xpathObj->nodesetval->nodeMax)
122     {
123         /* the Xpath has been understood and there are node */
124         for (int i = 0 ; i < xpathObj->nodesetval->nodeNr ; i++)
125         {
126             xmlAttrPtr attrib = xpathObj->nodesetval->nodeTab[i]->properties;
127             /* Get the properties of <module>  */
128             while (attrib != NULL)
129             {
130                 /* loop until when have read all the attributes */
131                 if (xmlStrEqual (attrib->name, (const xmlChar*)"name"))
132                 {
133                     /* we found the tag name */
134                     const char *str = (const char*)attrib->children->content;
135                     pstName = to_wide_string(str);
136                 }
137                 else if (xmlStrEqual(attrib->name, (const xmlChar*)"file"))
138                 {
139                     /* we found the tag activate */
140                     const char *str = (const char*)attrib->children->content;
141                     pstFileName = to_wide_string(str);
142                 }
143                 attrib = attrib->next;
144             }
145
146             if (pstName && pstFileName)
147             {
148                 std::wstring stFilename(wstPath);
149                 if (stFilename.empty() == false && *stFilename.rbegin() != DIR_SEPARATORW[0])
150                 {
151                     stFilename += DIR_SEPARATORW;
152                 }
153
154                 stFilename += pstFileName;
155                 lib->add(pstName, new types::MacroFile(pstName, stFilename, pstLibName));
156             }
157             else
158             {
159                 std::cout << pstName << " module not found." << std::endl;
160             }
161
162             if (pstName)
163             {
164                 FREE(pstName);
165                 pstName = NULL;
166             }
167
168             if (pstFileName)
169             {
170                 FREE(pstFileName);
171                 pstFileName = NULL;
172             }
173         }
174     }
175
176     if (xpathObj)
177     {
178         xmlXPathFreeObject(xpathObj);
179     }
180     if (xpathCtxt)
181     {
182         xmlXPathFreeContext(xpathCtxt);
183     }
184
185     if (_bAddInContext)
186     {
187         symbol::Context* ctx = symbol::Context::getInstance();
188         symbol::Symbol sym = symbol::Symbol(pstLibName);
189         if (ctx->isprotected(sym) == false)
190         {
191             ctx->put(symbol::Symbol(pstLibName), lib);
192         }
193         else
194         {
195             delete lib;
196             lib = NULL;
197         }
198     }
199
200     xmlFreeDoc(doc);
201     FREE(pstLibName);
202     return lib;
203 }
204
205 static char *GetXmlFileEncoding(std::string _filename)
206 {
207     char *encoding = NULL;
208     xmlDocPtr doc = NULL;
209
210     /* default */
211     encoding = os_strdup(DEFAULT_ENCODING);
212
213     doc = xmlParseFile(_filename.c_str());
214     if (doc)
215     {
216         if (doc->encoding)
217         {
218             if (encoding)
219             {
220                 free(encoding);
221                 encoding = NULL;
222             }
223             encoding = os_strdup((char*)doc->encoding);
224         }
225     }
226
227     xmlFreeDoc(doc);
228     return encoding;
229 }