EO: insert/extract 'list()' and '$+1' is now handled
[scilab.git] / scilab / modules / external_objects / src / cpp / ScilabObjects.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2012 - Scilab Enterprises - Calixte DENIZET
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.1-en.txt
10  *
11  */
12
13 #include "ScilabObjects.hxx"
14 #include <cstring>
15
16 #include <cstdio>
17 #include <vector>
18
19 extern "C" {
20     extern int C2F(varfunptr)(int *, int *, int *);
21 }
22
23 namespace org_modules_external_objects
24 {
25 bool ScilabObjects::isInit = false;
26 const char * ScilabObjects::_EOBJ[] = {"_EObj", "_EnvId", "_id"};
27 const char * ScilabObjects::_ECLASS[] = {"_EClass", "_EnvId", "_id"};
28 const char * ScilabObjects::_EVOID[] = {"_EVoid", "_EnvId", "_id"};
29 const char * ScilabObjects::_INVOKE_ = "!!_invoke_";
30
31 void ScilabObjects::initialization(ScilabAbstractEnvironment & env, void * pvApiCtx)
32 {
33     if (!isInit)
34     {
35         isInit = true;
36     }
37 }
38
39 int ScilabObjects::createNamedEnvironmentObject(int type, const char * name, int id, const int envId, void * pvApiCtx)
40 {
41     const char ** fields;
42     int * mlistaddr = 0;
43     SciErr err;
44
45     if (envId < 0)
46     {
47         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid environment"));
48     }
49
50     switch (type)
51     {
52         case EXTERNAL_OBJECT:
53             fields = static_cast<const char **>(_EOBJ);
54             break;
55         case EXTERNAL_CLASS:
56             fields = static_cast<const char **>(_ECLASS);
57             break;
58         case EXTERNAL_VOID:
59             fields = static_cast<const char **>(_EVOID);
60             break;
61         default :
62             fields = static_cast<const char **>(_EOBJ);
63             break;
64     }
65
66     err = createNamedMList(pvApiCtx, name, FIELDS_LENGTH, &mlistaddr);
67     if (err.iErr)
68     {
69         if (err.iErr == API_ERROR_INVALID_NAME)
70         {
71             throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable name: %s"), name);
72         }
73
74         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Cannot allocate memory"));
75     }
76
77     err = createMatrixOfStringInNamedList(pvApiCtx, name, mlistaddr, 1, 1, FIELDS_LENGTH, fields);
78     if (err.iErr)
79     {
80         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Cannot allocate memory"));
81     }
82
83     err = createMatrixOfInteger32InNamedList(pvApiCtx, name, mlistaddr, EXTERNAL_ENV_ID_POSITION, 1, 1, &envId);
84     if (err.iErr)
85     {
86         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Cannot allocate memory"));
87     }
88
89     err = createMatrixOfInteger32InNamedList(pvApiCtx, name, mlistaddr, EXTERNAL_OBJ_ID_POSITION, 1, 1, &id);
90     if (err.iErr)
91     {
92         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Cannot allocate memory"));
93     }
94
95     return 1;
96 }
97
98 void ScilabObjects::createEnvironmentObjectAtPos(int type, int pos, int id, const int envId, void * pvApiCtx)
99 {
100     const char ** fields = 0;
101     int * mlistaddr = 0;
102     SciErr err;
103
104     if (envId < 0)
105     {
106         throw ScilabAbstractEnvironmentException("Invalid environment");
107     }
108
109     switch (type)
110     {
111         case EXTERNAL_OBJECT:
112             fields = static_cast<const char **>(_EOBJ);
113             break;
114         case EXTERNAL_CLASS:
115             fields = static_cast<const char **>(_ECLASS);
116             break;
117         case EXTERNAL_VOID:
118             fields = static_cast<const char **>(_EVOID);
119             break;
120         default :
121             fields = static_cast<const char **>(_EOBJ);
122             break;
123     }
124
125     err = createMList(pvApiCtx, pos, FIELDS_LENGTH, &mlistaddr);
126     if (err.iErr)
127     {
128         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Cannot allocate memory"));
129     }
130
131     err = createMatrixOfStringInList(pvApiCtx, pos, mlistaddr, 1, 1, FIELDS_LENGTH, fields);
132     if (err.iErr)
133     {
134         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Cannot allocate memory"));
135     }
136
137     err = createMatrixOfInteger32InList(pvApiCtx, pos, mlistaddr, EXTERNAL_ENV_ID_POSITION, 1, 1, &envId);
138     if (err.iErr)
139     {
140         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Cannot allocate memory"));
141     }
142
143     err = createMatrixOfInteger32InList(pvApiCtx, pos, mlistaddr, EXTERNAL_OBJ_ID_POSITION, 1, 1, &id);
144     if (err.iErr)
145     {
146         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Cannot allocate memory"));
147     }
148 }
149
150 void ScilabObjects::copyInvocationMacroToStack(int pos, ScilabAbstractEnvironment & env, void * pvApiCtx)
151 {
152     static bool init = false;
153     static int id[nsiz];
154     static int interf = 0;
155     static int funnumber = 0;
156
157     if (!init)
158     {
159         init = true;
160         C2F(str2name)(const_cast<char *>(_INVOKE_), id, strlen(_INVOKE_));
161         int fins = Fin;
162         int funs = C2F(com).fun;
163         Fin = -1;
164         C2F(funs)(id);
165         funnumber = Fin;
166         interf = C2F(com).fun;
167         C2F(com).fun = funs;
168         Fin = fins;
169     }
170
171     int tops = Top;
172     // Remove 1 since varfunptr will increment Top
173     Top = Top - Rhs + pos - 1;
174
175     // Create a function pointer variable
176     C2F(varfunptr)(id, &interf, &funnumber);
177     C2F(intersci).ntypes[pos - 1] = '$';
178
179     Top = tops;
180
181     OptionsHelper::setCopyOccurred(true);
182 }
183
184 void ScilabObjects::removeTemporaryVars(const int envId, int * tmpvar)
185 {
186     if (tmpvar && *tmpvar)
187     {
188         ScilabAbstractEnvironment & env = ScilabEnvironments::getEnvironment(envId);
189         env.removeobject(tmpvar + 1, *tmpvar);
190         *tmpvar = 0;
191     }
192 }
193
194 void ScilabObjects::removeVar(int * addr, void * pvApiCtx)
195 {
196     SciErr err;
197     int type, row, col, * id;
198
199     err = getVarType(pvApiCtx, addr, &type);
200     if (err.iErr)
201     {
202         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
203     }
204
205     if (type == sci_mlist && (isExternalObjOrClass(addr, pvApiCtx)))
206     {
207         err = getMatrixOfInteger32InList(pvApiCtx, addr, EXTERNAL_OBJ_ID_POSITION, &row, &col, &id);
208         if (err.iErr)
209         {
210             throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
211         }
212
213         int envId = getEnvironmentId(addr, pvApiCtx);
214         ScilabAbstractEnvironment & env = ScilabEnvironments::getEnvironment(envId);
215
216         env.removeobject(*id);
217     }
218     else if (type == sci_strings)
219     {
220         char * varName = 0;
221         if (getAllocatedSingleString(pvApiCtx, addr, &varName))
222         {
223             throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
224         }
225
226         err = getVarAddressFromName(pvApiCtx, varName, &addr);
227         if (err.iErr)
228         {
229             freeAllocatedSingleString(varName);
230             return;
231         }
232
233         err = getVarType(pvApiCtx, addr, &type);
234         if (err.iErr)
235         {
236             freeAllocatedSingleString(varName);
237             throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
238         }
239
240         if (type == sci_mlist && isExternalObjOrClass(addr, pvApiCtx))
241         {
242             err = getMatrixOfInteger32InList(pvApiCtx, addr, EXTERNAL_OBJ_ID_POSITION, &row, &col, &id);
243             if (err.iErr)
244             {
245                 freeAllocatedSingleString(varName);
246                 throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
247             }
248
249             int envId = getEnvironmentId(addr, pvApiCtx);
250             ScilabAbstractEnvironment & env = ScilabEnvironments::getEnvironment(envId);
251
252             env.removeobject(*id);
253             deleteNamedVariable(pvApiCtx, varName);
254             freeAllocatedSingleString(varName);
255         }
256     }
257 }
258
259 bool ScilabObjects::unwrap(int idObj, int pos, const int envId, void * pvApiCtx)
260 {
261     if (idObj == 0)
262     {
263         // id == 0 <==> null object plugged on empty matrix
264         if (createEmptyMatrix(pvApiCtx, pos))
265         {
266             throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot create data"));
267         }
268         return true;
269     }
270
271     VariableType type = Nothing;
272     ScilabAbstractEnvironment & env = ScilabEnvironments::getEnvironment(envId);
273     const ScilabAbstractEnvironmentWrapper & wrapper = env.getWrapper();
274
275     type = env.isunwrappable(idObj);
276     switch (type)
277     {
278         case Nothing:
279             return false;
280         case Null:
281             if (createEmptyMatrix(pvApiCtx, pos))
282             {
283                 throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot create data"));
284             }
285             break;
286         case SingleDouble:
287             wrapper.unwrapdouble(idObj, ScilabDoubleStackAllocator(pvApiCtx, pos));
288             break;
289         case RowDouble:
290             wrapper.unwraprowdouble(idObj, ScilabDoubleStackAllocator(pvApiCtx, pos));
291             break;
292         case MatDouble:
293             wrapper.unwrapmatdouble(idObj, ScilabDoubleStackAllocator(pvApiCtx, pos));
294             break;
295         case SingleString:
296             wrapper.unwrapstring(idObj, ScilabStringStackAllocator(pvApiCtx, pos));
297             break;
298         case RowString:
299             wrapper.unwraprowstring(idObj, ScilabStringStackAllocator(pvApiCtx, pos));
300             break;
301         case MatString:
302             wrapper.unwrapmatstring(idObj, ScilabStringStackAllocator(pvApiCtx, pos));
303             break;
304         case SingleBoolean:
305             wrapper.unwrapboolean(idObj, ScilabBooleanStackAllocator(pvApiCtx, pos));
306             break;
307         case RowBoolean:
308             wrapper.unwraprowboolean(idObj, ScilabBooleanStackAllocator(pvApiCtx, pos));
309             break;
310         case MatBoolean:
311             wrapper.unwrapmatboolean(idObj, ScilabBooleanStackAllocator(pvApiCtx, pos));
312             break;
313         case SingleChar:
314             wrapper.unwrapchar(idObj, ScilabCharStackAllocator(pvApiCtx, pos));
315             break;
316         case RowChar:
317             wrapper.unwraprowchar(idObj, ScilabCharStackAllocator(pvApiCtx, pos));
318             break;
319         case MatChar:
320             wrapper.unwrapmatchar(idObj, ScilabCharStackAllocator(pvApiCtx, pos));
321             break;
322         case SingleUChar:
323             wrapper.unwrapuchar(idObj, ScilabUCharStackAllocator(pvApiCtx, pos));
324             break;
325         case RowUChar:
326             wrapper.unwraprowuchar(idObj, ScilabUCharStackAllocator(pvApiCtx, pos));
327             break;
328         case MatUChar:
329             wrapper.unwrapmatuchar(idObj, ScilabUCharStackAllocator(pvApiCtx, pos));
330             break;
331         case SingleShort:
332             wrapper.unwrapshort(idObj, ScilabShortStackAllocator(pvApiCtx, pos));
333             break;
334         case RowShort:
335             wrapper.unwraprowshort(idObj, ScilabShortStackAllocator(pvApiCtx, pos));
336             break;
337         case MatShort:
338             wrapper.unwrapmatshort(idObj, ScilabShortStackAllocator(pvApiCtx, pos));
339             break;
340         case SingleUShort:
341             wrapper.unwrapushort(idObj, ScilabUShortStackAllocator(pvApiCtx, pos));
342             break;
343         case RowUShort:
344             wrapper.unwraprowushort(idObj, ScilabUShortStackAllocator(pvApiCtx, pos));
345             break;
346         case MatUShort:
347             wrapper.unwrapmatushort(idObj, ScilabUShortStackAllocator(pvApiCtx, pos));
348             break;
349         case SingleInt:
350             wrapper.unwrapint(idObj, ScilabIntStackAllocator(pvApiCtx, pos));
351             break;
352         case RowInt:
353             wrapper.unwraprowint(idObj, ScilabIntStackAllocator(pvApiCtx, pos));
354             break;
355         case MatInt:
356             wrapper.unwrapmatint(idObj, ScilabIntStackAllocator(pvApiCtx, pos));
357             break;
358         case SingleUInt:
359             wrapper.unwrapuint(idObj, ScilabUIntStackAllocator(pvApiCtx, pos));
360             break;
361         case RowUInt:
362             wrapper.unwraprowuint(idObj, ScilabUIntStackAllocator(pvApiCtx, pos));
363             break;
364         case MatUInt:
365             wrapper.unwrapmatuint(idObj, ScilabUIntStackAllocator(pvApiCtx, pos));
366             break;
367         case SingleLong:
368             wrapper.unwraplong(idObj, ScilabLongStackAllocator(pvApiCtx, pos));
369             break;
370         case RowLong:
371             wrapper.unwraprowlong(idObj, ScilabLongStackAllocator(pvApiCtx, pos));
372             break;
373         case MatLong:
374             wrapper.unwrapmatlong(idObj, ScilabLongStackAllocator(pvApiCtx, pos));
375             break;
376         case SingleULong:
377             wrapper.unwrapulong(idObj, ScilabULongStackAllocator(pvApiCtx, pos));
378             break;
379         case RowULong:
380             wrapper.unwraprowulong(idObj, ScilabULongStackAllocator(pvApiCtx, pos));
381             break;
382         case MatULong:
383             wrapper.unwrapmatulong(idObj, ScilabULongStackAllocator(pvApiCtx, pos));
384             break;
385         case SingleFloat:
386             wrapper.unwrapfloat(idObj, ScilabFloatStackAllocator(pvApiCtx, pos));
387             break;
388         case RowFloat:
389             wrapper.unwraprowfloat(idObj, ScilabFloatStackAllocator(pvApiCtx, pos));
390             break;
391         case MatFloat:
392             wrapper.unwrapmatfloat(idObj, ScilabFloatStackAllocator(pvApiCtx, pos));
393             break;
394         case SingleComplex:
395             wrapper.unwrapcomplex(idObj, ScilabComplexStackAllocator(pvApiCtx, pos));
396             break;
397         case RowComplex:
398             wrapper.unwraprowcomplex(idObj, ScilabComplexStackAllocator(pvApiCtx, pos));
399             break;
400         case MatComplex:
401             wrapper.unwrapmatcomplex(idObj, ScilabComplexStackAllocator(pvApiCtx, pos));
402             break;
403         default:
404             return false;
405     }
406
407     return true;
408 }
409
410 int ScilabObjects::getEnvironmentId(int * addr, void * pvApiCtx)
411 {
412     SciErr err;
413     int row = 0, col = 0;
414     int * envId = 0;
415
416     err = getMatrixOfInteger32InList(pvApiCtx, addr, EXTERNAL_ENV_ID_POSITION, &row, &col, &envId);
417     if (err.iErr)
418     {
419         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
420     }
421
422     return *envId;
423 }
424
425 int ScilabObjects::getExternalId(int * addr, void * pvApiCtx)
426 {
427     SciErr err;
428     int row = 0, col = 0;
429     int * id = 0;
430
431     err = getMatrixOfInteger32InList(pvApiCtx, addr, EXTERNAL_OBJ_ID_POSITION, &row, &col, &id);
432     if (err.iErr)
433     {
434         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
435     }
436
437     return *id;
438 }
439
440 int ScilabObjects::getArgumentId(int * addr, int * tmpvars, const bool isRef, const bool isClass, const int envId, void * pvApiCtx)
441 {
442     SciErr err;
443     int typ, row = 0, col = 0, returnId;
444     const ScilabAbstractEnvironmentWrapper & wrapper = ScilabEnvironments::getEnvironment(envId).getWrapper();
445
446     err = getVarType(pvApiCtx, addr, &typ);
447     if (err.iErr)
448     {
449         removeTemporaryVars(envId, tmpvars);
450         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
451     }
452
453     if (isClass && typ != sci_mlist)
454     {
455         removeTemporaryVars(envId, tmpvars);
456         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("External Class expected"));
457     }
458
459     switch (typ)
460     {
461         case sci_matrix :
462         {
463             double * mat = 0;
464
465             if (isVarComplex(pvApiCtx, addr))
466             {
467                 double * imag = 0;
468                 err = getComplexMatrixOfDouble(pvApiCtx, addr, &row, &col, &mat, &imag);
469                 if (err.iErr)
470                 {
471                     removeTemporaryVars(envId, tmpvars);
472                     throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
473                 }
474
475                 returnId = wrap(row, col, mat, imag, wrapper, isRef);
476             }
477             else
478             {
479                 err = getMatrixOfDouble(pvApiCtx, addr, &row, &col, &mat);
480                 if (err.iErr)
481                 {
482                     removeTemporaryVars(envId, tmpvars);
483                     throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
484                 }
485
486                 returnId = wrap<double>(row, col, mat, wrapper, isRef);
487             }
488
489             tmpvars[++tmpvars[0]] = returnId;
490
491             return returnId;
492         }
493         case sci_poly :
494         {
495             /* '$+1' should be handled to ease insertion/extraction */
496             int nameLen = 5;
497             char name[nameLen];
498
499             err = getPolyVariableName(pvApiCtx, addr, name, &nameLen);
500             if (err.iErr)
501             {
502                 removeTemporaryVars(envId, tmpvars);
503                 throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
504             }
505
506             if (name[0] == '$' && nameLen == 1)
507             {
508                 err = getMatrixOfPoly(pvApiCtx, addr, &row, &col, NULL, NULL);
509                 if (err.iErr)
510                 {
511                     removeTemporaryVars(envId, tmpvars);
512                     throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
513                 }
514
515                 if (row * col != 1)
516                 {
517                     removeTemporaryVars(envId, tmpvars);
518                     throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
519                 }
520
521                 int coefs;
522                 err = getMatrixOfPoly(pvApiCtx, addr, &row, &col, &coefs, NULL);
523                 if (err.iErr)
524                 {
525                     removeTemporaryVars(envId, tmpvars);
526                     throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
527                 }
528
529                 // should be std::dynarray
530                 std::vector<double> mat = std::vector<double>(row * col * coefs);
531                 double* pMat = mat.data();
532                 err = getMatrixOfPoly(pvApiCtx, addr, &row, &col, &coefs, &pMat);
533                 if (err.iErr)
534                 {
535                     removeTemporaryVars(envId, tmpvars);
536                     throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
537                 }
538
539                 returnId = wrapper.wrapPoly(row * col * coefs, mat.data());
540             }
541             else
542             {
543                 removeTemporaryVars(envId, tmpvars);
544                 throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
545             }
546             return returnId;
547         }
548         case sci_ints :
549         {
550             int prec = 0;
551             void * ints = 0;
552
553             err = getMatrixOfIntegerPrecision(pvApiCtx, addr, &prec);
554             if (err.iErr)
555             {
556                 removeTemporaryVars(envId, tmpvars);
557                 throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
558             }
559
560             switch (prec)
561             {
562                 case SCI_INT8 :
563                     err = getMatrixOfInteger8(pvApiCtx, addr, &row, &col, (char**)(&ints));
564                     if (err.iErr)
565                     {
566                         removeTemporaryVars(envId, tmpvars);
567                         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
568                     }
569
570                     returnId = wrap<char>(row, col, static_cast<char *>(ints), wrapper, isRef);
571                     tmpvars[++tmpvars[0]] = returnId;
572                     return returnId;
573                 case SCI_UINT8 :
574                     err = getMatrixOfUnsignedInteger8(pvApiCtx, addr, &row, &col, (unsigned char**)(&ints));
575                     if (err.iErr)
576                     {
577                         removeTemporaryVars(envId, tmpvars);
578                         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
579                     }
580
581                     returnId = wrap<unsigned char>(row, col, static_cast<unsigned char *>(ints), wrapper, isRef);
582                     tmpvars[++tmpvars[0]] = returnId;
583                     return returnId;
584                 case SCI_INT16 :
585                     err = getMatrixOfInteger16(pvApiCtx, addr, &row, &col, (short**)(&ints));
586                     if (err.iErr)
587                     {
588                         removeTemporaryVars(envId, tmpvars);
589                         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
590                     }
591
592                     returnId = wrap<short>(row, col, static_cast<short *>(ints), wrapper, isRef);
593                     tmpvars[++tmpvars[0]] = returnId;
594                     return returnId;
595                 case SCI_UINT16 :
596                     err = getMatrixOfUnsignedInteger16(pvApiCtx, addr, &row, &col, (unsigned short**)(&ints));
597                     if (err.iErr)
598                     {
599                         removeTemporaryVars(envId, tmpvars);
600                         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
601                     }
602
603                     returnId = wrap<unsigned short>(row, col, static_cast<unsigned short *>(ints), wrapper, isRef);
604                     tmpvars[++tmpvars[0]] = returnId;
605                     return returnId;
606                 case SCI_INT32 :
607                     err = getMatrixOfInteger32(pvApiCtx, addr, &row, &col, (int**)(&ints));
608                     if (err.iErr)
609                     {
610                         removeTemporaryVars(envId, tmpvars);
611                         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
612                     }
613
614                     returnId = wrap<int>(row, col, static_cast<int *>(ints), wrapper, isRef);
615                     tmpvars[++tmpvars[0]] = returnId;
616                     return returnId;
617                 case SCI_UINT32 :
618                     err = getMatrixOfUnsignedInteger32(pvApiCtx, addr, &row, &col, (unsigned int**)(&ints));
619                     if (err.iErr)
620                     {
621                         removeTemporaryVars(envId, tmpvars);
622                         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
623                     }
624
625                     returnId = wrap<unsigned int>(row, col, static_cast<unsigned int *>(ints), wrapper, isRef);
626                     tmpvars[++tmpvars[0]] = returnId;
627                     return returnId;
628
629 #ifdef __SCILAB_INT64__
630                 case SCI_INT64 :
631                     err = getMatrixOfInteger64(pvApiCtx, addr, &row, &col, (long long**)(&ints));
632                     if (err.iErr)
633                     {
634                         removeTemporaryVars(envId, tmpvars);
635                         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
636                     }
637
638                     returnId = wrap<long long>(row, col, static_cast<long long *>(ints), wrapper, isRef);
639                     tmpvars[++tmpvars[0]] = returnId;
640                     return returnId;
641                 case SCI_UINT64 :
642                     err = getMatrixOfUnsignedInteger64(pvApiCtx, addr, &row, &col, (unsigned long long**)(&ints));
643                     if (err.iErr)
644                     {
645                         removeTemporaryVars(envId, tmpvars);
646                         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
647                     }
648
649                     returnId = wrap<unsigned long long>(row, col, static_cast<unsigned long long *>(ints), wrapper, isRef);
650                     tmpvars[++tmpvars[0]] = returnId;
651                     return returnId;
652 #endif
653             }
654
655             // invalid int code : should never be called
656             removeTemporaryVars(envId, tmpvars);
657             throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
658         }
659         case sci_strings :
660         {
661             char ** matS = NULL;
662             if (getAllocatedMatrixOfString(pvApiCtx, addr, &row, &col, &matS))
663             {
664                 removeTemporaryVars(envId, tmpvars);
665                 throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
666             }
667
668             returnId = wrap<char *>(row, col, matS, wrapper, isRef);
669             freeAllocatedMatrixOfString(row, col, matS);
670             tmpvars[++tmpvars[0]] = returnId;
671
672             return returnId;
673         }
674         case sci_boolean :
675         {
676             int * matB;
677
678             err = getMatrixOfBoolean(pvApiCtx, addr, &row, &col, &matB);
679             if (err.iErr)
680             {
681                 removeTemporaryVars(envId, tmpvars);
682                 throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
683             }
684
685             returnId = wrapBool(row, col, matB, wrapper, isRef);
686             tmpvars[++tmpvars[0]] = returnId;
687
688             return returnId;
689         }
690         case sci_list :
691         {
692             int length;
693
694             err = getListItemNumber(pvApiCtx, addr, &length);
695             if (err.iErr)
696             {
697                 removeTemporaryVars(envId, tmpvars);
698                 throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
699             }
700
701             // empty list
702             if (length <= 0)
703             {
704                 return 0;
705             }
706
707             // should be std::dynarray
708             std::vector<int> childrenIds = std::vector<int>(length + 1);
709
710             // loop all over the items
711             for (int i = 0; i < length; i++)
712             {
713                 int* pvItem;
714
715                 err = getListItemAddress(pvApiCtx, addr, i + 1, &pvItem);
716                 if (err.iErr)
717                 {
718                     removeTemporaryVars(envId, childrenIds.data());
719                     throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
720                 }
721
722                 getArgumentId(pvItem, childrenIds.data(), false, false, envId, pvApiCtx);
723             }
724
725             returnId = wrapper.wrapList(length, childrenIds.data());
726             tmpvars[++tmpvars[0]] = returnId;
727
728             return returnId;
729         }
730         case sci_mlist :
731         {
732             int * id = 0;
733             int type = getMListType(addr, pvApiCtx);
734             int eId = getEnvironmentId(addr, pvApiCtx);
735
736             if (type == EXTERNAL_INVALID)
737             {
738                 removeTemporaryVars(envId, tmpvars);
739                 throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("External object expected"));
740             }
741
742             err = getMatrixOfInteger32InList(pvApiCtx, addr, EXTERNAL_OBJ_ID_POSITION, &row, &col, &id);
743             if (err.iErr)
744             {
745                 removeTemporaryVars(envId, tmpvars);
746                 throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid variable: cannot retrieve the data"));
747             }
748
749             if (eId != envId && id != 0)
750             {
751                 removeTemporaryVars(envId, tmpvars);
752                 throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Incompatible External object"));
753             }
754
755             if (isClass)
756             {
757                 if (type == EXTERNAL_CLASS)
758                 {
759                     return *id;
760                 }
761                 else
762                 {
763                     removeTemporaryVars(envId, tmpvars);
764                     throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("External Class expected"));
765                 }
766             }
767
768             if (type == EXTERNAL_OBJECT || type == EXTERNAL_CLASS)
769             {
770                 return *id;
771             }
772             else if (type == EXTERNAL_VOID)
773             {
774                 return -1;
775             }
776
777             break;
778         }
779         default :
780         {
781             removeTemporaryVars(envId, tmpvars);
782             throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Unable to wrap. Unmanaged datatype (%d) ?"), typ);
783         }
784     }
785
786     return -1;
787 }
788
789 int ScilabObjects::getMListType(int * mlist, void * pvApiCtx)
790 {
791     char * mlist_type[3];
792     char * mtype = 0;
793     int lengths[3];
794     int rows, cols;
795     int type;
796
797     // OK it's crappy... but it works and it is performant...
798
799     if (mlist[0] == 0)
800     {
801         return EXTERNAL_VOID;
802     }
803
804     if (mlist[0] != sci_mlist || mlist[1] != 3)
805     {
806         return EXTERNAL_INVALID;
807     }
808
809     if (mlist[6] != sci_strings || mlist[7] != 1 || mlist[8] != 3)
810     {
811         // first field is not a matrix 1x3 of strings
812         return EXTERNAL_INVALID;
813     }
814
815     if (mlist[11] - 1 == strlen("_EClass") && mlist[14] == 36 && mlist[15] == -14 && mlist[16] == -12 && mlist[17] == 21 && mlist[18] == 10 && mlist[19] == 28 && mlist[20] == 28)
816     {
817         return EXTERNAL_CLASS;
818     }
819
820     if (mlist[11] - 1 == strlen("_EObj") && mlist[14] == 36 && mlist[15] == -14 && mlist[16] == -24 && mlist[17] == 11 && mlist[18] == 19)
821     {
822         return EXTERNAL_OBJECT;
823     }
824
825     if (mlist[11] - 1 == strlen("_EVoid") && mlist[14] == 36 && mlist[15] == -14 && mlist[16] == -31 && mlist[17] == 24 && mlist[18] == 18 && mlist[19] == 13)
826     {
827         return EXTERNAL_VOID;
828     }
829
830     return EXTERNAL_INVALID;
831 }
832
833 bool ScilabObjects::isValidExternal(int * mlist, void * pvApiCtx)
834 {
835     int type = getMListType(mlist, pvApiCtx);
836     return type == EXTERNAL_OBJECT || type == EXTERNAL_CLASS;
837 }
838
839 bool ScilabObjects::isExternalObj(int * mlist, void * pvApiCtx)
840 {
841     return getMListType(mlist, pvApiCtx) == EXTERNAL_OBJECT;
842 }
843
844 bool ScilabObjects::isExternalClass(int * mlist, void * pvApiCtx)
845 {
846     return getMListType(mlist, pvApiCtx) == EXTERNAL_CLASS;
847 }
848
849 bool ScilabObjects::isExternalObjOrClass(int * mlist, void * pvApiCtx)
850 {
851     int type = getMListType(mlist, pvApiCtx);
852     return type == EXTERNAL_OBJECT || type == EXTERNAL_CLASS;
853 }
854
855 bool ScilabObjects::isExternalVoid(int * mlist, void * pvApiCtx)
856 {
857     return getMListType(mlist, pvApiCtx) == EXTERNAL_VOID;
858 }
859
860 char * ScilabObjects::getSingleString(int pos, void * pvApiCtx)
861 {
862     SciErr err;
863     int * addr = 0;
864     char * str = 0;
865
866     err = getVarAddressFromPosition(pvApiCtx, pos, &addr);
867     if (err.iErr)
868     {
869         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid String"));
870     }
871
872     if (!isStringType(pvApiCtx, addr))
873     {
874         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("A single string expected"));
875     }
876
877     if (!isScalar(pvApiCtx, addr))
878     {
879         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("A single String expected"));
880     }
881
882     if (getAllocatedSingleString(pvApiCtx, addr, &str))
883     {
884         throw ScilabAbstractEnvironmentException(__LINE__, __FILE__, gettext("Invalid String"));
885     }
886
887     return str;
888 }
889
890 int ScilabObjects::isPositiveIntegerAtAddress(int * addr, void * pvApiCtx)
891 {
892     SciErr err;
893     int typ = 0, row, col, prec;
894
895     err = getVarDimension(pvApiCtx, addr, &row, &col);
896     if (err.iErr)
897     {
898         return -1;
899     }
900
901     if (row != 1 || col != 1)
902     {
903         return -1;
904     }
905
906     err = getVarType(pvApiCtx, addr, &typ);
907     if (err.iErr)
908     {
909         return -1;
910     }
911
912     if (typ == sci_ints)
913     {
914         err = getMatrixOfIntegerPrecision(pvApiCtx, addr, &prec);
915         if (err.iErr)
916         {
917             return -1;
918         }
919         switch (prec)
920         {
921             case SCI_INT8:
922             {
923                 char * cvalue = 0;
924                 err = getMatrixOfInteger8(pvApiCtx, addr, &row, &col, &cvalue);
925                 if (err.iErr)
926                 {
927                     return -1;
928                 }
929                 return (int)(*cvalue);
930             }
931             break;
932             case SCI_UINT8:
933             {
934                 unsigned char * ucvalue = 0;
935                 err = getMatrixOfUnsignedInteger8(pvApiCtx, addr, &row, &col, &ucvalue);
936                 if (err.iErr)
937                 {
938                     return -1;
939                 }
940                 return (int)(*ucvalue);
941             }
942             break;
943             case SCI_INT16:
944             {
945                 short * svalue = 0;
946                 err = getMatrixOfInteger16(pvApiCtx, addr, &row, &col, &svalue);
947                 if (err.iErr)
948                 {
949                     return -1;
950                 }
951                 return (int)(*svalue);
952             }
953             break;
954             case SCI_UINT16:
955             {
956                 unsigned short * usvalue = 0;
957                 err = getMatrixOfUnsignedInteger16(pvApiCtx, addr, &row, &col, &usvalue);
958                 if (err.iErr)
959                 {
960                     return -1;
961                 }
962                 return (int)(*usvalue);
963             }
964             break;
965             case SCI_INT32:
966             {
967                 int * ivalue = 0;
968                 err = getMatrixOfInteger32(pvApiCtx, addr, &row, &col, &ivalue);
969                 if (err.iErr)
970                 {
971                     return -1;
972                 }
973                 return (int)(*ivalue);
974             }
975             break;
976             case SCI_UINT32:
977             {
978                 unsigned int * uivalue = 0;
979                 err = getMatrixOfUnsignedInteger32(pvApiCtx, addr, &row, &col, &uivalue);
980                 if (err.iErr)
981                 {
982                     return -1;
983                 }
984                 return (int)(*uivalue);
985             }
986             break;
987 #ifdef __SCILAB_INT64__
988             case SCI_INT64:
989             {
990                 long long * llvalue = 0;
991                 err = getMatrixOfInteger64(pvApiCtx, addr, &row, &col, &llvalue);
992                 if (err.iErr)
993                 {
994                     return -1;
995                 }
996                 return (int)(*llvalue);
997             }
998             break;
999             case SCI_UINT64:
1000             {
1001                 unsigned long long * ullvalue = 0;
1002                 err = getMatrixOfUnsignedInteger64(pvApiCtx, addr, &row, &col, &ullvalue);
1003                 if (err.iErr)
1004                 {
1005                     return -1;
1006                 }
1007                 return (int)(*ullvalue);
1008             }
1009             break;
1010 #endif
1011             default:
1012                 return -1;
1013         }
1014     }
1015     else if (typ == sci_matrix)
1016     {
1017         double * dvalue = 0;
1018
1019         if (isVarComplex(pvApiCtx, addr))
1020         {
1021             return -1;
1022         }
1023
1024         err = getMatrixOfDouble(pvApiCtx, addr, &row, &col, &dvalue);
1025         if (err.iErr)
1026         {
1027             return -1;
1028         }
1029
1030         if (*dvalue - (double)(int)(*dvalue) == 0.0)
1031         {
1032             return (int)(*dvalue);
1033         }
1034     }
1035
1036     return -1;
1037 }
1038 }