[ast] improved polynomial display with unicode superscripts
[scilab.git] / scilab / modules / ast / src / cpp / types / function.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2008-2008 - DIGITEO - Antoine ELIAS
4  *  Copyright (C) 2010-2010 - DIGITEO - Bruno JOFRET
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 #include <algorithm>
18 #include <sstream>
19 #include <vector>
20 #include "function.hxx"
21 #include "double.hxx"
22 #include "gatewaystruct.hxx"
23 #include "configvariable.hxx"
24 #include "scilabWrite.hxx"
25
26 extern "C"
27 {
28 #include "core_math.h"
29 #include "charEncoding.h"
30 #include "Scierror.h"
31 #include "sciprint.h"
32 #include "localization.h"
33 #include "sci_path.h"
34 #include "sci_malloc.h"
35 #include "os_string.h"
36 #include "lasterror.h"
37 #include "dynamic_module.h"
38 #include "functions_manager.h"
39 }
40
41 // dummy function definition for non nwni compatible modules
42 static void dummy()
43 {
44     char* fname = wide_string_to_UTF8(ConfigVariable::getWhere().back().call->getName().c_str());
45     Scierror(999, _("Scilab '%s' function disabled in -nogui or -nwni mode.\n"), fname);
46     FREE(fname);
47 }
48 static types::Function::ReturnValue sci_dummy_in_NWNI(types::typed_list &/*in*/, int /*_iRetCount*/, types::typed_list &/*out*/)
49 {
50     dummy();
51     return types::Function::Error;
52 }
53 static types::Function::ReturnValue sci_dummy_in_NWNI_OPT(types::typed_list &/*in*/, types::optional_list &/*opt*/, int /*_iRetCount*/, types::typed_list &/*out*/)
54 {
55     dummy();
56     return types::Function::Error;
57 }
58 static int sci_dummy_in_NWNI_OLDC(char * /*fname*/, void* /*pvApiCtx*/)
59 {
60     dummy();
61     return 1;
62 }
63 static int sci_dummy_in_NWNI_MEX(int /*nlhs*/, int** /*plhs*/, int /*nrhs*/, int** /*prhs*/)
64 {
65     dummy();
66     return 1;
67 }
68 static int sci_dummy_in_NWNI_C(scilabEnv /*env*/, int /*nin*/, scilabVar* /*in*/, int /*nopt*/, scilabOpt /*opt*/, int /*nout*/, scilabVar* /*out*/)
69 {
70     dummy();
71     return 1;
72 }
73
74 // Function Class definition
75 namespace types
76 {
77 Function* Function::createFunction(const std::wstring& _wstName, GW_FUNC _pFunc, const std::wstring& _wstModule)
78 {
79     return new Function(_wstName, _pFunc, NULL, _wstModule);
80 }
81
82 Function* Function::createFunction(const std::wstring& _wstName, GW_FUNC_OPT _pFunc, const std::wstring& _wstModule)
83 {
84     return new OptFunction(_wstName, _pFunc, NULL, _wstModule);
85 }
86
87 Function* Function::createFunction(const std::wstring& _wstName, OLDGW_FUNC _pFunc, const std::wstring& _wstModule)
88 {
89     return new WrapFunction(_wstName, _pFunc, NULL, _wstModule);
90 }
91
92 Function* Function::createFunction(const std::wstring& _wstName, MEXGW_FUNC _pFunc, const std::wstring& _wstModule)
93 {
94     return new WrapMexFunction(_wstName, _pFunc, NULL, _wstModule);
95 }
96
97 Function* Function::createFunction(const std::wstring& _wstName, GW_FUNC _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule)
98 {
99     return new Function(_wstName, _pFunc, _pLoadDeps, _wstModule);
100 }
101
102 Function* Function::createFunction(const std::wstring& _wstName, GW_FUNC_OPT _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule)
103 {
104     return new OptFunction(_wstName, _pFunc, _pLoadDeps, _wstModule);
105 }
106
107 Function* Function::createFunction(const std::wstring& _wstName, OLDGW_FUNC _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule)
108 {
109     return new WrapFunction(_wstName, _pFunc, _pLoadDeps, _wstModule);
110 }
111
112 Function* Function::createFunction(const std::wstring& _wstName, MEXGW_FUNC _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule)
113 {
114     return new WrapMexFunction(_wstName, _pFunc, _pLoadDeps, _wstModule);
115 }
116
117 Function* Function::createFunction(const std::wstring& _wstName, const std::wstring& _wstEntryPointName, const std::wstring& _wstLibName, FunctionType _iType, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule, bool _bCloseLibAfterCall)
118 {
119     if (isNonNwniModule(_wstModule.data()))
120     {
121         switch (_iType)
122         {
123             case FunctionType::EntryPointOldC:
124                 return new WrapFunction(_wstName, &sci_dummy_in_NWNI_OLDC, NULL, _wstModule);
125             case FunctionType::EntryPointCPP:
126                 return new Function(_wstName, &sci_dummy_in_NWNI, NULL, _wstModule);
127             case FunctionType::EntryPointMex:
128                 return new WrapMexFunction(_wstName, &sci_dummy_in_NWNI_MEX, NULL, _wstModule);
129             case FunctionType::EntryPointCPPOpt:
130                 return new OptFunction(_wstName, &sci_dummy_in_NWNI_OPT, NULL, _wstModule);
131             case FunctionType::EntryPointC:
132                 return new WrapCFunction(_wstName, &sci_dummy_in_NWNI_C, NULL, _wstModule);
133         }
134     }
135     else
136     {
137         return new DynamicFunction(_wstName, _wstEntryPointName, _wstLibName, _iType, _pLoadDeps, _wstModule, _bCloseLibAfterCall);
138     }
139     
140     // must never append
141     return NULL;
142 }
143
144 Function* Function::createFunction(const std::wstring& _wstName, const std::wstring& _wstEntryPointName, const std::wstring& _wstLibName, FunctionType _iType, const std::wstring& _wstLoadDepsName, const std::wstring& _wstModule, bool _bCloseLibAfterCall)
145 {
146     if (isNonNwniModule(_wstModule.data()))
147     {
148         switch (_iType)
149         {
150             case FunctionType::EntryPointOldC:
151                 return new WrapFunction(_wstName, &sci_dummy_in_NWNI_OLDC, NULL, _wstModule);
152             case FunctionType::EntryPointCPP:
153                 return new Function(_wstName, &sci_dummy_in_NWNI, NULL, _wstModule);
154             case FunctionType::EntryPointMex:
155                 return new WrapMexFunction(_wstName, &sci_dummy_in_NWNI_MEX, NULL, _wstModule);
156             case FunctionType::EntryPointCPPOpt:
157                 return new OptFunction(_wstName, &sci_dummy_in_NWNI_OPT, NULL, _wstModule);
158             case FunctionType::EntryPointC:
159                 return new WrapCFunction(_wstName, &sci_dummy_in_NWNI_C, NULL, _wstModule);
160         }
161     }
162     else
163     {
164         return new DynamicFunction(_wstName, _wstEntryPointName, _wstLibName, _iType, _wstLoadDepsName, _wstModule, _bCloseLibAfterCall);
165     }
166
167     // must never append
168     return NULL;
169 }
170
171 Function* Function::createFunction(const std::wstring& _wstName, GW_C_FUNC _pFunc, const std::wstring& _wstModule)
172 {
173     return new WrapCFunction(_wstName, _pFunc, NULL, _wstModule);
174 }
175
176 Function* Function::createFunction(const std::wstring& _wstName, GW_C_FUNC _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule)
177 {
178     return new WrapCFunction(_wstName, _pFunc, _pLoadDeps, _wstModule);
179 }
180
181
182 Function::Function(const std::wstring& _wstName, GW_FUNC _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule) : Callable(), m_pFunc(_pFunc), m_pLoadDeps(_pLoadDeps)
183 {
184     setName(_wstName);
185     char* s = wide_string_to_UTF8(m_wstName.data());
186     m_stName = s;
187     FREE(s);
188
189     setModule(_wstModule);
190 }
191
192 Function::~Function()
193 {
194
195 }
196
197
198 Function::ReturnValue Function::call(typed_list &in, optional_list &/*opt*/, int _iRetCount, typed_list &out)
199 {
200     int ret = 1;
201     if (m_pLoadDeps != NULL)
202     {
203         ret = m_pLoadDeps(m_wstName);
204     }
205
206     if (ret == 0)
207     {
208         return Error;
209     }
210
211     return this->m_pFunc(in, _iRetCount, out);
212 }
213
214 void Function::whoAmI()
215 {
216     std::cout << "types::Function";
217 }
218
219 bool Function::toString(std::wostringstream& /*ostr*/)
220 {
221     // display nothing. ie : c = cos
222     return true;
223 }
224
225 Function* Function::clone()
226 {
227     IncreaseRef();
228     return this;
229 }
230
231 bool Function::operator==(const InternalType& it)
232 {
233     if (!const_cast<InternalType &>(it).isFunction())
234     {
235         return false;
236     }
237     return this->getFunc() == const_cast<InternalType &>(it).getAs<Function>()->getFunc();
238 }
239
240 OptFunction::OptFunction(const std::wstring& _wstName, GW_FUNC_OPT _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule)
241 {
242     m_wstName = _wstName;
243     char* s = wide_string_to_UTF8(m_wstName.data());
244     m_stName = s;
245     FREE(s);
246     m_pFunc = _pFunc;
247     m_pLoadDeps = _pLoadDeps;
248     m_wstModule = _wstModule;
249 }
250
251 OptFunction::OptFunction(OptFunction* _pWrapFunction)
252 {
253     m_wstModule  = _pWrapFunction->getModule();
254     m_wstName    = _pWrapFunction->getName();
255     char* s = wide_string_to_UTF8(m_wstName.data());
256     m_stName = s;
257     FREE(s);
258     m_pFunc = _pWrapFunction->getFunc();
259     m_pLoadDeps = _pWrapFunction->getDeps();
260 }
261
262 OptFunction* OptFunction::clone()
263 {
264     return new OptFunction(this);
265 }
266
267 Function::ReturnValue OptFunction::call(typed_list &in, optional_list &opt, int _iRetCount, typed_list &out)
268 {
269     int ret = 1;
270     if (m_pLoadDeps != NULL)
271     {
272         ret = m_pLoadDeps(m_wstName);
273     }
274
275     if (ret == 0)
276     {
277         return Error;
278     }
279
280     return this->m_pFunc(in, opt, _iRetCount, out);
281 }
282
283 WrapFunction::WrapFunction(const std::wstring& _wstName, OLDGW_FUNC _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule)
284 {
285     m_wstName = _wstName;
286     m_pOldFunc = _pFunc;
287     m_wstModule = _wstModule;
288     char* s = wide_string_to_UTF8(m_wstName.data());
289     m_stName = s;
290     FREE(s);
291     m_pLoadDeps = _pLoadDeps;
292 }
293
294 WrapFunction::WrapFunction(WrapFunction* _pWrapFunction)
295 {
296     m_wstModule = _pWrapFunction->getModule();
297     m_wstName = _pWrapFunction->getName();
298     char* s = wide_string_to_UTF8(m_wstName.data());
299     m_stName = s;
300     FREE(s);
301     m_pOldFunc  = _pWrapFunction->getFunc();
302     m_pLoadDeps = _pWrapFunction->getDeps();
303 }
304
305 WrapFunction* WrapFunction::clone()
306 {
307     return new WrapFunction(this);
308 }
309
310 Function::ReturnValue WrapFunction::call(typed_list &in, optional_list &opt, int _iRetCount, typed_list &out)
311 {
312     int ret = 1;
313     int inSize = (int)in.size();
314     int optSize = (int)opt.size();
315     int isRef = checkReferenceModule(m_wstModule.c_str());
316
317     if (m_pLoadDeps != NULL)
318     {
319         ret = m_pLoadDeps(m_wstName);
320     }
321
322     if (ret == 0)
323     {
324         return Error;
325     }
326
327     ReturnValue retVal = Callable::OK;
328     GatewayStruct gStr;
329     _iRetCount = std::max(1, _iRetCount);
330     gStr.m_iIn = inSize + optSize;
331     gStr.m_iOut = _iRetCount;
332
333     //copy input parameter to prevent calling gateway modifies input data
334     typed_list inCopy;
335
336     if (isRef == 0)
337     {
338         for (int i = 0; i < inSize; i++)
339         {
340             inCopy.push_back(in[i]->clone());
341         }
342     }
343     else
344     {
345         for (int i = 0; i < inSize; i++)
346         {
347             inCopy.push_back(in[i]);
348         }
349     }
350     gStr.m_pIn = &inCopy;
351     gStr.m_pOpt = &opt;
352     typed_list::value_type tmpOut[MAX_OUTPUT_VARIABLE];
353     std::fill_n(tmpOut, MAX_OUTPUT_VARIABLE, static_cast<typed_list::value_type>(0));
354     gStr.m_pOut = tmpOut;
355     gStr.m_piRetCount = &_iRetCount;
356     gStr.m_pstName = m_stName.data();
357     // we should use a stack array of the max size to avoid dynamic alloc.
358     std::vector<int> outOrder(_iRetCount < 1 ? 1 : _iRetCount, -1);
359     gStr.m_pOutOrder = outOrder.data();
360
361     //call gateway
362     m_pOldFunc(const_cast<char*>(m_stName.data()), reinterpret_cast<int*>(&gStr));
363     if (ConfigVariable::isError())
364     {
365         retVal = Callable::Error;
366         ConfigVariable::resetError();
367     }
368     else
369     {
370         for (std::size_t i(0); i != (size_t)_iRetCount && outOrder[i] != -1 && outOrder[i] != 0; ++i)
371         {
372             if (outOrder[i] - 1 < gStr.m_iIn)
373             {
374                 std::size_t const iPos(outOrder[i] - 1);
375                 //protect variable to deletion
376                 inCopy[iPos]->IncreaseRef();
377                 if (inCopy[iPos]->isDouble() && ((types::Double*)inCopy[iPos])->isViewAsInteger())
378                 {
379                     types::Double* pD = inCopy[iPos]->getAs<types::Double>();
380                     pD->convertFromInteger();
381                 }
382
383                 if (inCopy[iPos]->isDouble() && ((types::Double*)inCopy[iPos])->isViewAsZComplex())
384                 {
385                     types::Double* pD = inCopy[iPos]->getAs<types::Double>();
386                     pD->convertFromZComplex();
387                 }
388
389                 out.push_back(inCopy[iPos]);
390             }
391             else
392             {
393                 std::size_t const iPos(outOrder[i] - gStr.m_iIn - 1);
394                 if (tmpOut[iPos]->isDouble() && ((types::Double*)tmpOut[iPos])->isViewAsInteger())
395                 {
396                     types::Double* pD = tmpOut[iPos]->getAs<types::Double>();
397                     pD->convertFromInteger();
398                 }
399
400                 if (tmpOut[iPos]->isDouble() && ((types::Double*)tmpOut[iPos])->isViewAsZComplex())
401                 {
402                     types::Double* pD = tmpOut[iPos]->getAs<types::Double>();
403                     pD->convertFromZComplex();
404                 }
405
406                 out.push_back(tmpOut[iPos]);
407                 tmpOut[iPos] = 0;
408             }
409         }
410     }
411
412     for (std::size_t i(0); i != MAX_OUTPUT_VARIABLE; ++i)
413     {
414         if (tmpOut[i])
415         {
416             tmpOut[i]->killMe();
417         }
418     }
419
420     //clean input copy
421     if (isRef == 0)
422     {
423         //protect outputs
424         int size = (int)out.size();
425         for (int i = 0; i < size; i++)
426         {
427             out[i]->IncreaseRef();
428         }
429
430         for (int i = 0; i < inSize; i++)
431         {
432             inCopy[i]->killMe();
433         }
434
435         //unprotect outputs
436         for (int i = 0; i < size; i++)
437         {
438             out[i]->DecreaseRef();
439         }
440     }
441     else
442     {
443         for (int i = 0; i < in.size(); ++i)
444         {
445             if (in[i]->isDouble() && ((types::Double*)in[i])->isViewAsInteger())
446             {
447                 types::Double* pD = in[i]->getAs<types::Double>();
448                 pD->convertFromInteger();
449             }
450         }
451
452     }
453
454     for (auto i : opt)
455     {
456         if (i.second->isDouble() && ((types::Double*)i.second)->isViewAsInteger())
457         {
458             types::Double* pD = i.second->getAs<types::Double>();
459             pD->convertFromInteger();
460         }
461     }
462
463     return retVal;
464 }
465
466 WrapMexFunction::WrapMexFunction(const std::wstring& _wstName, MEXGW_FUNC _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule)
467 {
468     m_wstName = _wstName;
469     char* s = wide_string_to_UTF8(m_wstName.data());
470     m_stName = s;
471     FREE(s);
472     m_pOldFunc = _pFunc;
473     m_wstModule = _wstModule;
474     m_pLoadDeps = _pLoadDeps;
475 }
476
477 WrapMexFunction::WrapMexFunction(WrapMexFunction* _pWrapFunction)
478 {
479     m_wstModule = _pWrapFunction->getModule();
480     char* s = wide_string_to_UTF8(m_wstName.data());
481     m_stName = s;
482     FREE(s);
483     m_wstName = _pWrapFunction->getName();
484     m_pOldFunc = _pWrapFunction->getFunc();
485     m_pLoadDeps = _pWrapFunction->getDeps();
486 }
487
488 WrapMexFunction* WrapMexFunction::clone()
489 {
490     return new WrapMexFunction(this);
491 }
492
493 Function::ReturnValue WrapMexFunction::call(typed_list &in, optional_list &/*opt*/, int _iRetCount, typed_list &out)
494 {
495     typedef struct __MAXARRAY__ {
496         int* ptr;
497     } mxArray;
498
499     int ret = 1;
500     if (m_pLoadDeps != NULL)
501     {
502         ret = m_pLoadDeps(m_wstName);
503     }
504
505     if (ret == 0)
506     {
507         return Error;
508     }
509
510     ReturnValue retVal = Callable::OK;
511
512     char* name = wide_string_to_UTF8(getName().c_str());
513     ConfigVariable::setMexFunctionName(name);
514     FREE(name);
515
516     int nlhs = _iRetCount;
517     mxArray** plhs = new mxArray*[nlhs];
518     memset(plhs, 0x00, sizeof(mxArray*) * nlhs);
519
520     int nrhs = (int)in.size();
521     mxArray** prhs = new mxArray*[nrhs];
522     for (int i = 0; i < nrhs; i++)
523     {
524         prhs[i] = new mxArray;
525         prhs[i]->ptr = (int*)(in[i]);
526     }
527
528     try
529     {
530         m_pOldFunc(nlhs, (int**)plhs, nrhs, (int**)prhs);
531     }
532     catch (const ast::InternalError& ie)
533     {
534         delete[] plhs;
535         delete[] prhs;
536         throw ie;
537     }
538
539     if (_iRetCount == 1 && plhs[0] == NULL)
540     {
541         //dont copy empty values, juste return "no value"
542         return retVal;
543     }
544
545     for (int i = 0; i < nlhs; i++)
546     {
547         out.push_back((types::InternalType*)plhs[i]->ptr);
548         delete plhs[i];
549     }
550
551     delete[] plhs;
552
553     for (int i = 0; i < nrhs; i++)
554     {
555         delete prhs[i];
556     }
557
558     delete[] prhs;
559     return retVal;
560 }
561
562 WrapCFunction::WrapCFunction(const std::wstring& _wstName, GW_C_FUNC _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule)
563 {
564     m_wstName = _wstName;
565     char* s = wide_string_to_UTF8(m_wstName.data());
566     m_stName = s;
567     FREE(s);
568     m_pCFunc = _pFunc;
569     m_wstModule = _wstModule;
570     m_pLoadDeps = _pLoadDeps;
571 }
572
573 WrapCFunction::WrapCFunction(WrapCFunction* _pWrapFunction)
574 {
575     m_wstModule = _pWrapFunction->getModule();
576     char* s = wide_string_to_UTF8(m_wstName.data());
577     m_stName = s;
578     FREE(s);
579     m_wstName = _pWrapFunction->getName();
580     m_pCFunc = _pWrapFunction->getFunc();
581     m_pLoadDeps = _pWrapFunction->getDeps();
582 }
583
584 WrapCFunction* WrapCFunction::clone()
585 {
586     return new WrapCFunction(this);
587 }
588
589 Function::ReturnValue WrapCFunction::call(typed_list& in, optional_list& opt, int _iRetCount, typed_list& out)
590 {
591     if (m_pLoadDeps != NULL)
592     {
593         if (m_pLoadDeps(m_wstName) == 0)
594         {
595             return Error;
596         }
597     }
598
599     ReturnValue retVal = OK;
600
601     try
602     {
603         GatewayCStruct gcs;
604         gcs.name = m_stName;
605         out.resize(_iRetCount, NULL);
606         if (m_pCFunc((void*)&gcs, (int)in.size(), (scilabVar*)(in.data()), (int)opt.size(), (scilabOpt)&opt, _iRetCount, (scilabVar*)(out.data())))
607         {
608             retVal = Error;
609         }
610     }
611     catch (const ast::InternalError& ie)
612     {
613         throw ie;
614     }
615
616     if (retVal == OK)
617     {
618         if (_iRetCount == 1 && out[0] == NULL)
619         {
620             //dont copy empty values, juste return "no value"
621             out.clear();
622             return retVal;
623         }
624     }
625
626     return retVal;
627 }
628
629 DynamicFunction::DynamicFunction(const std::wstring& _wstName, const std::wstring& _wstEntryPointName, const std::wstring& _wstLibName, FunctionType _iType, const std::wstring& _wstLoadDepsName, const std::wstring& _wstModule, bool _bCloseLibAfterCall)
630 {
631     m_wstName               = _wstName;
632     char* s = wide_string_to_UTF8(m_wstName.data());
633     m_stName = s;
634     FREE(s);
635     m_wstLibName = _wstLibName;
636     m_wstModule             = _wstModule;
637     m_wstEntryPoint         = _wstEntryPointName;
638     m_wstLoadDepsName       = _wstLoadDepsName;
639     m_pLoadDeps             = NULL;
640     m_bCloseLibAfterCall    = _bCloseLibAfterCall;
641     m_iType                 = _iType;
642     m_pFunc                 = NULL;
643     m_pOptFunc              = NULL;
644     m_pOldFunc              = NULL;
645     m_pMexFunc              = NULL;
646     m_pFunction             = NULL;
647     m_pCFunc                = NULL;
648 }
649
650 DynamicFunction::DynamicFunction(const std::wstring& _wstName, const std::wstring& _wstEntryPointName, const std::wstring& _wstLibName, FunctionType _iType, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule, bool _bCloseLibAfterCall)
651 {
652     m_wstName               = _wstName;
653     char* s = wide_string_to_UTF8(m_wstName.data());
654     m_stName = s;
655     FREE(s);
656     m_wstLibName = _wstLibName;
657     m_wstModule             = _wstModule;
658     m_wstEntryPoint         = _wstEntryPointName;
659     m_pLoadDeps             = _pLoadDeps;
660     m_wstLoadDepsName       = L"";
661     m_bCloseLibAfterCall    = _bCloseLibAfterCall;
662     m_iType                 = _iType;
663     m_pFunc                 = NULL;
664     m_pOptFunc              = NULL;
665     m_pOldFunc              = NULL;
666     m_pMexFunc              = NULL;
667     m_pFunction             = NULL;
668     m_pCFunc                = NULL;
669 }
670
671 Function::ReturnValue DynamicFunction::call(typed_list &in, optional_list &opt, int _iRetCount, typed_list &out)
672 {
673     if (m_pFunction == NULL)
674     {
675         if (Init() != OK)
676         {
677             return Error;
678         }
679     }
680
681     /*call function*/
682     if (m_pFunction->call(in, opt, _iRetCount, out) != OK)
683     {
684         return Error;
685     }
686
687     /*Close lib is mandatory*/
688     if (m_bCloseLibAfterCall)
689     {
690         Clear();
691     }
692
693     return OK;
694 }
695
696 DynamicFunction::~DynamicFunction()
697 {
698     if (m_pFunction)
699     {
700         delete m_pFunction;
701     }
702 }
703
704 Callable::ReturnValue DynamicFunction::Init()
705 {
706     /*Load library*/
707     if (m_wstLibName.empty())
708     {
709         Scierror(999, _("%s: Library name must not be empty\n."), m_wstName.c_str());
710         return Error;
711     }
712
713     DynLibHandle hLib = getDynModule(m_wstLibName.c_str());
714     if (hLib == 0)
715     {
716         char* pstLibName = wide_string_to_UTF8(m_wstLibName.c_str());
717         hLib = LoadDynLibrary(pstLibName);
718
719         if (hLib == 0)
720         {
721             //2nd chance for linux !
722 #ifndef _MSC_VER
723             char* pstError = strdup(GetLastDynLibError());
724
725             /* Haven't been able to find the lib with dlopen...
726             * This can happen for two reasons:
727             * - the lib must be dynamically linked
728             * - Some silly issues under Suse (see bug #2875)
729             * Note that we are handling only the "source tree build"
730             * because libraries are split (they are in the same directory
731             * in the binary)
732             */
733             wchar_t* pwstScilabPath = getSCIW();
734             wchar_t pwstModulesPath[] = L"/modules/";
735             wchar_t pwstLTDir[] =  L".libs/";
736
737             /* Build the full path to the library */
738             int iPathToLibLen = (wcslen(pwstScilabPath) + wcslen(pwstModulesPath) + wcslen(m_wstModule.c_str()) + wcslen(L"/") + wcslen(pwstLTDir) + wcslen(m_wstLibName.c_str()) + 1);
739             wchar_t* pwstPathToLib = (wchar_t*)MALLOC(iPathToLibLen * sizeof(wchar_t));
740             os_swprintf(pwstPathToLib, iPathToLibLen, L"%ls%ls%ls/%ls%ls", pwstScilabPath, pwstModulesPath, m_wstModule.c_str(), pwstLTDir, m_wstLibName.c_str());
741             FREE(pwstScilabPath);
742             char* pstPathToLib = wide_string_to_UTF8(pwstPathToLib);
743             FREE(pwstPathToLib);
744             hLib = LoadDynLibrary(pstPathToLib);
745
746             if (hLib == 0)
747             {
748                 Scierror(999, _("An error has been detected while loading %s: %s\n"), pstLibName, pstError);
749                 FREE(pstError);
750
751                 pstError = GetLastDynLibError();
752                 Scierror(999, _("An error has been detected while loading %s: %s\n"), pstPathToLib, pstError);
753
754                 FREE(pstLibName);
755                 FREE(pstPathToLib);
756                 return Error;
757             }
758             FREE(pstPathToLib);
759             FREE(pstError);
760 #else
761             char* pstError = wide_string_to_UTF8(m_wstLibName.c_str());
762             Scierror(999, _("Impossible to load %s library\n"), pstError);
763             FREE(pstError);
764             FREE(pstLibName);
765             return Error;
766 #endif
767         }
768         FREE(pstLibName);
769         addDynModule(m_wstLibName.c_str(), hLib);
770
771         /*Load deps*/
772         if (m_wstLoadDepsName.empty() == false && m_pLoadDeps == NULL)
773         {
774             char* pstLoadDepsName = wide_string_to_UTF8(m_wstLoadDepsName.c_str());
775             m_pLoadDeps = (LOAD_DEPS)GetDynLibFuncPtr(hLib, pstLoadDepsName);
776             FREE(pstLoadDepsName);
777         }
778
779     }
780
781     /*Load gateway*/
782     if (m_wstName != L"")
783     {
784         char* pstEntryPoint = wide_string_to_UTF8(m_wstEntryPoint.c_str());
785         switch (m_iType)
786         {
787             case EntryPointCPPOpt :
788                 m_pOptFunc = (GW_FUNC_OPT)GetDynLibFuncPtr(hLib, pstEntryPoint);
789                 break;
790             case EntryPointCPP :
791                 m_pFunc = (GW_FUNC)GetDynLibFuncPtr(hLib, pstEntryPoint);
792                 break;
793             case EntryPointOldC :
794                 m_pOldFunc = (OLDGW_FUNC)GetDynLibFuncPtr(hLib, pstEntryPoint);
795                 break;
796             case EntryPointMex:
797                 m_pMexFunc = (MEXGW_FUNC)GetDynLibFuncPtr(hLib, pstEntryPoint);
798                 break;
799             case EntryPointC:
800                 m_pCFunc = (GW_C_FUNC)GetDynLibFuncPtr(hLib, pstEntryPoint);
801                 break;
802         }
803
804         FREE(pstEntryPoint);
805     }
806
807     if (m_pFunc == NULL && m_pOldFunc == NULL && m_pMexFunc == NULL && m_pOptFunc == NULL && m_pCFunc == NULL)
808     {
809         char* pstEntry = wide_string_to_UTF8(m_wstEntryPoint.c_str());
810         char* pstLib = wide_string_to_UTF8(m_wstLibName.c_str());
811         Scierror(999, _("Impossible to load %s function in %s library: %s\n"), pstEntry, pstLib, GetLastDynLibError());
812         FREE(pstEntry);
813         FREE(pstLib);
814         return Error;
815     }
816
817     switch (m_iType)
818     {
819         case EntryPointCPPOpt :
820             m_pFunction = new OptFunction(m_wstName, m_pOptFunc, m_pLoadDeps, m_wstModule);
821             break;
822         case EntryPointCPP :
823             m_pFunction = new Function(m_wstName, m_pFunc, m_pLoadDeps, m_wstModule);
824             break;
825         case EntryPointOldC :
826             m_pFunction = new WrapFunction(m_wstName, m_pOldFunc, m_pLoadDeps, m_wstModule);
827             break;
828         case EntryPointMex:
829             m_pFunction = new WrapMexFunction(m_wstName, m_pMexFunc, m_pLoadDeps, m_wstModule);
830             break;
831         case EntryPointC:
832             m_pFunction = new WrapCFunction(m_wstName, m_pCFunc, m_pLoadDeps, m_wstModule);
833             break;
834     }
835
836     if (m_pFunction == NULL)
837     {
838         return Error;
839     }
840     return OK;
841 }
842
843 void DynamicFunction::Clear()
844 {
845     m_pFunc     = NULL;
846     m_pOldFunc  = NULL;
847     m_pMexFunc  = NULL;
848 }
849
850 }