fix library path
[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 "stricmp.h"
22 #include "os_strdup.h"
23 #include "expandPathVariable.h"
24 #include "PATH_MAX.h"
25 #include <libxml/xpath.h>
26 #include <libxml/xmlreader.h>
27 }
28
29 #define DEFAULT_ENCODING "UTF-8"
30
31 static char *GetXmlFileEncoding(std::string _filename);
32
33 types::Library* loadlib(std::wstring _wstXML, bool _isFile, bool _bAddInContext)
34 {
35     types::Library* lib = NULL;
36
37     wchar_t* pwstPathLib = expandPathVariableW((wchar_t*)_wstXML.c_str());
38
39     std::wstring wstOriginalPath(_wstXML);
40     std::wstring wstFile(pwstPathLib);
41     std::wstring wstPath(pwstPathLib);
42     FREE(pwstPathLib);
43
44     if (_isFile)
45     {
46         size_t pos = wstPath.find_last_of(L"/\\");
47         wstPath = wstPath.substr(0, pos);
48         pos = wstOriginalPath.find_last_of(L"/\\");
49         wstOriginalPath = wstOriginalPath.substr(0, pos + 1); //with ending /
50     }
51     else
52     {
53         if (wstFile.empty() == false && *wstFile.rbegin() != DIR_SEPARATORW[0])
54         {
55             wstFile += DIR_SEPARATORW;
56         }
57
58         wstFile += L"lib";
59     }
60
61     char* pstFile = wide_string_to_UTF8(wstFile.c_str());
62     char *encoding = GetXmlFileEncoding(pstFile);
63
64     /* Don't care about line return / empty line */
65     xmlKeepBlanksDefault(0);
66     /* check if the XML file has been encoded with utf8 (unicode) or not */
67     if (stricmp("utf-8", encoding))
68     {
69         std::wcout << "Error: Not a valid module file " << pstFile << " (encoding not 'utf-8') Encoding '" << encoding << "' found." << std::endl;
70         FREE(pstFile);
71         free(encoding);
72         return NULL;
73     }
74
75     xmlDocPtr doc;
76     xmlXPathContextPtr xpathCtxt    = NULL;
77     xmlXPathObjectPtr xpathObj      = NULL;
78     wchar_t* pstName                = NULL;
79     wchar_t* pstLibName             = NULL;
80     wchar_t* pstFileName            = NULL;
81
82     free(encoding);
83
84     doc = xmlParseFile(pstFile);
85
86     if (doc == NULL)
87     {
88         std::cout << "Error: Could not parse file " << pstFile << std::endl;
89         FREE(pstFile);
90         return NULL;
91     }
92
93     FREE(pstFile);
94
95     lib = new types::Library(wstOriginalPath);
96
97     xpathCtxt = xmlXPathNewContext(doc);
98     xpathObj = xmlXPathEval((const xmlChar*)"//scilablib", xpathCtxt);
99     if (xpathObj && xpathObj->nodesetval->nodeMax)
100     {
101         xmlAttrPtr attrib = xpathObj->nodesetval->nodeTab[0]->properties;
102         if (xmlStrEqual (attrib->name, (const xmlChar*)"name"))
103         {
104             /* we found the tag name */
105             const char *str = (const char*)attrib->children->content;
106             pstLibName = to_wide_string(str);
107             xmlXPathFreeObject(xpathObj);
108         }
109         else
110         {
111             if (xpathCtxt)
112             {
113                 xmlXPathFreeContext(xpathCtxt);
114             }
115             xmlXPathFreeObject(xpathObj);
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::getInstance()->put(symbol::Symbol(pstLibName), lib);
188     }
189
190     xmlFreeDoc(doc);
191     FREE(pstLibName);
192     return lib;
193 }
194
195 static char *GetXmlFileEncoding(std::string _filename)
196 {
197     char *encoding = NULL;
198     xmlDocPtr doc = NULL;
199
200     /* default */
201     encoding = os_strdup(DEFAULT_ENCODING);
202
203     doc = xmlParseFile(_filename.c_str());
204     if (doc)
205     {
206         if (doc->encoding)
207         {
208             if (encoding)
209             {
210                 free(encoding);
211                 encoding = NULL;
212             }
213             encoding = os_strdup((char*)doc->encoding);
214         }
215     }
216
217     xmlFreeDoc(doc);
218     return encoding;
219 }