1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2012 - Scilab Enterprises - Calixte DENIZET
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15 
16 #include <vector>
17 
18 #include "XMLObject.hxx"
19 #include "XMLDocument.hxx"
20 #include "XMLElement.hxx"
21 #include "XMLNs.hxx"
22 #include "XMLAttr.hxx"
23 #include "XMLNodeList.hxx"
24 
25 extern "C"
26 {
27 #include <string.h>
28 #include <stdio.h>
29 #include "gw_xml.h"
30 #include "Scierror.h"
31 #include "api_scilab.h"
32 #include "xml_mlist.h"
33 #include "xml_constants.h"
34 #include "localization.h"
35 #include "os_string.h"
36 }
37 
38 using namespace org_modules_xml;
39 
40 /*--------------------------------------------------------------------------*/
41 
42 /**
43  * Creates a string on stack
44  * @param fname the function name
45  * @param str the string to put
46  * @param pos the stack position
47  * @return 1 if all is ok, else 0
48  */
createStringOnStack(char * fname,const char * str,int pos,void * pvApiCtx)49 int createStringOnStack(char * fname, const char * str, int pos, void* pvApiCtx)
50 {
51     SciErr err;
52 
53     if (!str)
54     {
55         str = "";
56     }
57 
58     if (strchr(str, '\n'))
59     {
60         char * tok = os_strdup(str);
61         char * stok = tok;
62         std::vector<char *> vector = std::vector<char *>();
63 
64         tok = strtok(tok, "\n");
65         while (tok)
66         {
67             vector.push_back(tok);
68             tok = strtok(0, "\n");
69         }
70 
71         if (vector.size())
72         {
73             err = createMatrixOfString(pvApiCtx, pos, (int)vector.size(), 1, const_cast<const char * const *>(&(vector[0])));
74         }
75         else
76         {
77             err = createMatrixOfDouble(pvApiCtx, pos, 0, 0, 0);
78         }
79 
80         free(stok);
81     }
82     else
83     {
84         err = createMatrixOfString(pvApiCtx, pos, 1, 1, const_cast<const char * const *>(&str));
85     }
86 
87     if (err.iErr)
88     {
89         printError(&err, 0);
90         return 0;
91     }
92 
93     return 1;
94 }
95 /*--------------------------------------------------------------------------*/
96 /**
97  * Creates a new variable on stack according to the requested field
98  * @param fname the function name
99  * @param doc the document
100  * @param field the field name
101  * @param pos the stack position
102  * @return 1 if all is ok, else 0
103  */
createVariableOnStack(char * fname,org_modules_xml::XMLDocument & doc,const char * field,int pos,void * pvApiCtx)104 int createVariableOnStack(char * fname, org_modules_xml::XMLDocument & doc, const char * field, int pos, void* pvApiCtx)
105 {
106     if (!strcmp("root", field))
107     {
108         const XMLElement * e = doc.getRoot();
109         if (!e)
110         {
111             Scierror(999, gettext("%s: No root element.\n"), fname, field);
112             return 0;
113         }
114         return e->createOnStack(pos, pvApiCtx);
115     }
116     else if (!strcmp("url", field))
117     {
118         return createStringOnStack(fname, doc.getDocumentURL(), pos, pvApiCtx);
119     }
120     else
121     {
122         Scierror(999, gettext("%s: Unknown field: %s\n"), fname, field);
123         return 0;
124     }
125 }
126 /*--------------------------------------------------------------------------*/
127 
128 /**
129  * Creates a new variable on stack according to the requested field
130  * @param fname the function name
131  * @param elem the element
132  * @param field the field name
133  * @param pos the stack position
134  * @return 1 if all is ok, else 0
135  */
createVariableOnStack(char * fname,XMLElement & elem,const char * field,int pos,void * pvApiCtx)136 int createVariableOnStack(char * fname, XMLElement & elem, const char * field, int pos, void* pvApiCtx)
137 {
138     if (!strcmp("name", field))
139     {
140         return createStringOnStack(fname, elem.getNodeName(), pos, pvApiCtx);
141     }
142     else if (!strcmp("namespace", field))
143     {
144         const XMLNs * ns = elem.getNodeNameSpace();
145         if (ns)
146         {
147             return ns->createOnStack(pos, pvApiCtx);
148         }
149         else
150         {
151             createMatrixOfDouble(pvApiCtx, pos, 0, 0, 0);
152             return 1;
153         }
154     }
155     else if (!strcmp("content", field))
156     {
157         const char * content = elem.getNodeContent();
158         int ret = createStringOnStack(fname, content, pos, pvApiCtx);
159         xmlFree(const_cast<char *>(content));
160         return ret;
161     }
162     else if (!strcmp("type", field))
163     {
164         return createStringOnStack(fname, nodes_type[elem.getNodeType() - 1], pos, pvApiCtx);
165     }
166     else if (!strcmp("parent", field))
167     {
168         const XMLElement * parent = elem.getParentElement();
169         if (parent)
170         {
171             return parent->createOnStack(pos, pvApiCtx);
172         }
173         else
174         {
175             createMatrixOfDouble(pvApiCtx, pos, 0, 0, 0);
176             return 1;
177         }
178     }
179     else if (!strcmp("attributes", field))
180     {
181         return elem.getAttributes()->createOnStack(pos, pvApiCtx);
182     }
183     else if (!strcmp("children", field))
184     {
185         return elem.getChildren()->createOnStack(pos, pvApiCtx);
186     }
187     else if (!strcmp("line", field))
188     {
189         double line = (double)elem.getDefinitionLine();
190         SciErr err = createMatrixOfDouble(pvApiCtx, pos, 1, 1, &line);
191         if (err.iErr)
192         {
193             printError(&err, 0);
194             Scierror(999, _("%s: Memory allocation error.\n"), fname);
195             return 0;
196         }
197 
198         return 1;
199     }
200     else
201     {
202         Scierror(999, gettext("%s: Unknown field: %s\n"), fname, field);
203     }
204     return 0;
205 }
206 /*--------------------------------------------------------------------------*/
207 
208 /**
209  * Creates a new variable on stack according to the requested field
210  * @param fname the function name
211  * @param ns the namespace
212  * @param field the field name
213  * @param pos the stack position
214  * @return 1 if all is ok, else 0
215  */
createVariableOnStack(char * fname,XMLNs & ns,const char * field,int pos,void * pvApiCtx)216 int createVariableOnStack(char * fname, XMLNs & ns, const char * field, int pos, void* pvApiCtx)
217 {
218     if (!strcmp("href", field))
219     {
220         return createStringOnStack(fname, ns.getHref(), pos, pvApiCtx);
221     }
222     else if (!strcmp("prefix", field))
223     {
224         return createStringOnStack(fname, ns.getPrefix(), pos, pvApiCtx);
225     }
226     else
227     {
228         Scierror(999, gettext("%s: Unknown field: %s\n"), fname, field);
229         return 0;
230     }
231 }
232 /*--------------------------------------------------------------------------*/
233 
234 /**
235  * Function to handle extraction in different XMLObjects
236  * @param fname the function name
237  * @param fname_len the function name length
238  */
239 template<class T>
sci_extraction(char * fname,void * pvApiCtx)240 int sci_extraction(char * fname, void* pvApiCtx)
241 {
242     T * t;
243     int id;
244     SciErr err;
245     int * fieldaddr = 0;
246     int * mlistaddr = 0;
247     char * field = 0;
248     int ret;
249 
250     CheckLhs(0, 1);
251     CheckRhs(2, 2);
252 
253     err = getVarAddressFromPosition(pvApiCtx, 1, &fieldaddr);
254     if (err.iErr)
255     {
256         printError(&err, 0);
257         return 0;
258     }
259 
260     if (!isStringType(pvApiCtx, fieldaddr))
261     {
262         Scierror(999, gettext("%s: Wrong type for input argument #%i: string expected.\n"), fname, 1);
263         return 0;
264     }
265 
266     err = getVarAddressFromPosition(pvApiCtx, 2, &mlistaddr);
267     if (err.iErr)
268     {
269         printError(&err, 0);
270         Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, 2);
271         return 0;
272     }
273 
274     if (getAllocatedSingleString(pvApiCtx, fieldaddr, &field) != 0)
275     {
276         Scierror(999, _("%s: No more memory.\n"), fname);
277         return 0;
278     }
279     id = getXMLObjectId(mlistaddr, pvApiCtx);
280 
281     t = XMLObject::getFromId<T>(id);
282     if (!t)
283     {
284         freeAllocatedSingleString(field);
285         Scierror(999, gettext("%s: XML object does not exist.\n"), fname);
286         return 0;
287     }
288 
289     ret = createVariableOnStack(fname, *t, const_cast<char *>(field), Rhs + 1, pvApiCtx);
290     freeAllocatedSingleString(field);
291     if (ret)
292     {
293         LhsVar(1) = Rhs + 1;
294     }
295     else
296     {
297         LhsVar(1) = 0;
298     }
299     PutLhsVar();
300 
301     return 0;
302 }
303