32d3f71af130018c887d09cc296632586a37922b
[scilab.git] / scilab / modules / string / src / c / stringToComplex.c
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2010-2011 - DIGITEO - Allan CORNET
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 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <math.h>
16 #include <ctype.h>
17 #include <wctype.h>
18 #include "stringToComplex.h"
19 #include "stringToDouble.h"
20 #include "sci_malloc.h"
21 #include "os_string.h"
22 #include "BOOL.h"
23 #include "strsubst.h"
24 /* ========================================================================== */
25 #define PlusChar '+'
26 #define PlusCharW L'+'
27 #define LessChar '-'
28 #define LessCharW L'-'
29 #define ComplexCharI 'i'
30 #define ComplexCharIW L'i'
31 #define ComplexCharJ 'j'
32 #define ComplexCharJW L'j'
33 #define ComplexScilab "%i"
34 #define ComplexScilabW L"%i"
35 #define ComplexI "i"
36 #define ComplexIW L"i"
37 /* ========================================================================== */
38 #ifndef _MSC_VER
39 #ifndef strnicmp
40 #define strnicmp strncasecmp
41 #endif
42 #else
43 #define stricmp _stricmp
44 #endif
45 #ifdef _MSC_VER
46 #undef strnicmp
47 #define strnicmp _strnicmp
48 #endif
49 /* ========================================================================== */
50 static int ParseNumber(const char* tx);
51 static int ParseNumberW(const wchar_t* tx);
52 static stringToComplexError ParseComplexValue(const char *tx, BOOL bConvertByNAN, double *real, double *imag);
53 static stringToComplexError ParseComplexValueW(const wchar_t *tx, BOOL bConvertByNAN, double *real, double *imag);
54 static char* midstring(const char *tx, size_t pos, int nb);
55 static wchar_t* midstringW(const wchar_t *tx, size_t pos, int nb);
56 static char *leftstring(const char *tx, size_t pos);
57 static wchar_t* leftstringW(const wchar_t* tx, size_t pos);
58 static BOOL is_unit_imaginary (const char *src, double *im);
59 static BOOL is_unit_imaginaryW (const wchar_t* src, double *im);
60 static double returnNAN(void);
61 /* ========================================================================== */
62 complexArray *stringsToComplexArray(const char **pSTRs, int nbElements,
63                                     const char *decimal,
64                                     BOOL bConvertByNAN,
65                                     stringToComplexError *ierr)
66 {
67     complexArray *pComplexArray = NULL;
68
69     *ierr = STRINGTOCOMPLEX_ERROR;
70     if (nbElements <= 0)
71     {
72         return NULL;
73     }
74
75     if (pSTRs == NULL)
76     {
77         *ierr = STRINGTOCOMPLEX_MEMORY_ALLOCATION;
78     }
79     else
80     {
81         pComplexArray = createComplexArrayEmpty(nbElements);
82         if (pComplexArray)
83         {
84             int i = 0;
85             for (i = 0; i < nbElements; i++)
86             {
87                 doublecomplex dComplexValue = stringToComplex(pSTRs[i], decimal, bConvertByNAN, ierr);
88                 if (*ierr != STRINGTOCOMPLEX_NO_ERROR)
89                 {
90                     freeComplexArray(pComplexArray);
91                     return NULL;
92                 }
93                 else
94                 {
95                     pComplexArray->realPart[i] = dComplexValue.r;
96                     pComplexArray->imagPart[i] = dComplexValue.i;
97                 }
98             }
99             cleanImagPartComplexArray(pComplexArray);
100         }
101         else
102         {
103             *ierr = STRINGTOCOMPLEX_MEMORY_ALLOCATION;
104         }
105     }
106     return pComplexArray;
107 }
108 /* ========================================================================== */
109 doublecomplex stringToComplex(const char *pSTR, const char *decimal, BOOL bConvertByNAN, stringToComplexError *ierr)
110 {
111     doublecomplex dComplexValue;
112     *ierr = STRINGTOCOMPLEX_ERROR;
113
114     dComplexValue.r = 0.;
115     dComplexValue.i = 0.;
116
117     if (pSTR)
118     {
119         double real = 0.;
120         double imag = 0.;
121         char *pStrTemp = strsub((char*)pSTR, " ", "");
122
123         if (pStrTemp)
124         {
125             char *pStrFormatted = strsub(pStrTemp, decimal, ".");
126             FREE(pStrTemp);
127
128             if (pStrFormatted)
129             {
130                 int lenStrFormatted = (int) strlen(pStrFormatted);
131
132                 /* case .4 replaced by 0.4 */
133                 if (pStrFormatted[0] == '.')
134                 {
135                     /* case .4 replaced by 0.4 */
136                     char *pstStrTemp = (char*)MALLOC(sizeof(char) * (lenStrFormatted + strlen("0") + 1));
137                     strcpy(pstStrTemp, "0");
138                     strcat(pstStrTemp, pStrFormatted);
139                     FREE(pStrFormatted);
140                     pStrFormatted = pstStrTemp;
141                 }
142
143                 if (lenStrFormatted > 1)
144                 {
145                     if (((pStrFormatted[0] == '+') || (pStrFormatted[0] == '-')) &&
146                             (pStrFormatted[1] == '.'))
147                     {
148                         /* case +.4 replaced by +0.4 */
149                         char *pstStrTemp = strsub(pStrFormatted, "+.", "+0.");
150                         FREE(pStrFormatted);
151
152                         /* case -.4 replaced by -0.4 */
153                         pStrFormatted = strsub(pstStrTemp, "-.", "-0.");
154                         FREE(pstStrTemp);
155                     }
156                 }
157
158                 /* Case: "i", "+i", "-i", and with "j"  */
159                 if (is_unit_imaginary (pStrFormatted, &imag))
160                 {
161                     *ierr = STRINGTOCOMPLEX_NO_ERROR;
162                     dComplexValue.r = 0.;
163                     dComplexValue.i = imag;
164                 }
165                 else
166                 {
167                     *ierr = ParseComplexValue(pStrFormatted, bConvertByNAN, &real, &imag);
168                 }
169                 FREE(pStrFormatted);
170             }
171         }
172         dComplexValue.r = real;
173         dComplexValue.i = imag;
174     }
175     return dComplexValue;
176 }
177 /* ========================================================================== */
178 doublecomplex stringToComplexW(const wchar_t *pSTR, const wchar_t *decimal, BOOL bConvertByNAN, stringToComplexError *ierr)
179 {
180     doublecomplex dComplexValue;
181     *ierr = STRINGTOCOMPLEX_ERROR;
182
183     dComplexValue.r = 0.;
184     dComplexValue.i = 0.;
185
186     if (pSTR)
187     {
188         double real = 0.;
189         double imag = 0.;
190         wchar_t *pStrTemp = wcssub(pSTR, L" ", L"");
191
192         if (pStrTemp)
193         {
194             wchar_t *pStrFormatted = wcssub(pStrTemp, decimal, L".");
195             FREE(pStrTemp);
196
197             if (pStrFormatted)
198             {
199                 int lenStrFormatted = (int) wcslen(pStrFormatted);
200
201                 /* case .4 replaced by 0.4 */
202                 if (pStrFormatted[0] == '.')
203                 {
204                     /* case .4 replaced by 0.4 */
205                     wchar_t *pstStrTemp = (wchar_t*)MALLOC(sizeof(wchar_t) * (lenStrFormatted + wcslen(L"0") + 1));
206                     wcscpy(pstStrTemp, L"0");
207                     wcscat(pstStrTemp, pStrFormatted);
208                     FREE(pStrFormatted);
209                     pStrFormatted = pstStrTemp;
210                 }
211
212                 if (lenStrFormatted > 1)
213                 {
214                     if (((pStrFormatted[0] == '+') || (pStrFormatted[0] == '-')) &&
215                             (pStrFormatted[1] == '.'))
216                     {
217                         /* case +.4 replaced by +0.4 */
218                         wchar_t *pstStrTemp = wcssub(pStrFormatted, L"+.", L"+0.");
219                         FREE(pStrFormatted);
220
221                         /* case -.4 replaced by -0.4 */
222                         pStrFormatted = wcssub(pstStrTemp, L"-.", L"-0.");
223                         FREE(pstStrTemp);
224                     }
225                 }
226
227                 /* Case: "i", "+i", "-i", and with "j"  */
228                 if (is_unit_imaginaryW(pStrFormatted, &imag))
229                 {
230                     *ierr = STRINGTOCOMPLEX_NO_ERROR;
231                     dComplexValue.r = 0.;
232                     dComplexValue.i = imag;
233                 }
234                 else
235                 {
236                     *ierr = ParseComplexValueW(pStrFormatted, bConvertByNAN, &real, &imag);
237                 }
238                 FREE(pStrFormatted);
239             }
240         }
241         dComplexValue.r = real;
242         dComplexValue.i = imag;
243     }
244     return dComplexValue;
245 }
246 /* ========================================================================== */
247
248 static int ParseNumber(const char* tx)
249 {
250     int lookahead = 0;
251     int len = 0;
252
253     if (tx[len] == NULL)
254     {
255         return lookahead;
256     }
257     if (tx[len] < 0)
258     {
259         return lookahead;
260     }
261
262     // Special cases: constants
263     if (strlen(tx) >= 5 && (strncmp(tx, "+%eps", 5) == 0 || strncmp(tx, "-%eps", 5) == 0 || strncmp(tx, "+%nan", 5) == 0 || strncmp(tx, "-%nan", 5) == 0 || strncmp(tx, "+%inf", 5) == 0 || strncmp(tx, "-%inf", 5) == 0))
264     {
265         return 5;
266     }
267     else if (strlen(tx) >= 4 && (strncmp(tx, "%eps", 4) == 0 || strncmp(tx, "+%pi", 4) == 0 || strncmp(tx, "-%pi", 4) == 0 ||
268                                  strncmp(tx, "+Inf", 4) == 0 || strncmp(tx, "-Inf", 4) == 0 || strncmp(tx, "+Nan", 4) == 0 ||
269                                  strncmp(tx, "-Nan", 4) == 0 || strncmp(tx, "%nan", 4) == 0 || strncmp(tx, "%inf", 4) == 0 ))
270     {
271         return 4;
272     }
273     else if (strlen(tx) >= 3 && (strncmp(tx, "+%e", 3) == 0 || strncmp(tx, "-%e", 3) == 0 || strncmp(tx, "%pi", 3) == 0 ||
274                                  strncmp(tx, "Nan", 3) == 0 || strncmp(tx, "Inf", 3) == 0 || strncmp(tx, "%pi", 3) == 0))
275     {
276         return 3;
277     }
278     else if (strlen(tx) >= 2 && strncmp(tx, "%e", 2) == 0)
279     {
280         return 2;
281     }
282
283     if ((tx[len] == '+') || (tx[len] == '-'))
284     {
285         len++;
286     }
287
288     while (isdigit(tx[len]))
289     {
290         len++;
291     }
292     lookahead = len;
293
294     if (tx[lookahead] == '.')
295     {
296         lookahead++;
297         len = 0;
298         while (isdigit(tx[len + lookahead]))
299         {
300             len++;
301         }
302         lookahead += len;
303     }
304
305     if ((tx[lookahead] == 'E') || (tx[lookahead] == 'e') ||
306             (tx[lookahead] == 'D') || (tx[lookahead] == 'd'))
307     {
308
309         lookahead++;
310         if ((tx[lookahead] == '+') || (tx[lookahead] == '-'))
311         {
312             lookahead++;
313         }
314
315         len = 0;
316         while (isdigit(tx[len + lookahead]))
317         {
318             len++;
319         }
320
321         lookahead += len;
322     }
323     return lookahead;
324 }
325 /* ========================================================================== */
326 static int ParseNumberW(const wchar_t* tx)
327 {
328     int lookahead = 0;
329     int len = 0;
330
331     if (tx[len] == NULL)
332     {
333         return lookahead;
334     }
335     if (tx[len] < 0)
336     {
337         return lookahead;
338     }
339
340     if ((tx[len] == L'+') || (tx[len] == L'-'))
341     {
342         len++;
343     }
344
345     while (iswdigit(tx[len]))
346     {
347         len++;
348     }
349     lookahead = len;
350
351     if (tx[lookahead] == L'.')
352     {
353         lookahead++;
354         len = 0;
355         while (iswdigit(tx[len + lookahead]))
356         {
357             len++;
358         }
359         lookahead += len;
360     }
361
362     if ((tx[lookahead] == L'E') || (tx[lookahead] == L'e') ||
363             (tx[lookahead] == L'D') || (tx[lookahead] == L'd'))
364     {
365
366         lookahead++;
367         if ((tx[lookahead] == L'+') || (tx[lookahead] == L'-'))
368         {
369             lookahead++;
370         }
371
372         len = 0;
373         while (iswdigit(tx[len + lookahead]))
374         {
375             len++;
376         }
377
378         lookahead += len;
379     }
380     return lookahead;
381 }
382 /* ========================================================================== */
383 static stringToComplexError ParseComplexValue(const char *tx, BOOL bConvertByNAN, double *real, double *imag)
384 {
385     stringToDoubleError ierrDouble = STRINGTODOUBLE_NO_ERROR;
386     stringToComplexError ierr = STRINGTOCOMPLEX_NO_ERROR;
387     char *rnum_string = NULL;
388     char *inum_string = NULL;
389     size_t lnum = 0;
390     BOOL haveImagI = FALSE;
391     char *modifiedTxt = NULL;
392     int i = 0;
393
394     *real = stringToDouble(tx, FALSE, &ierrDouble);
395     *imag = 0;
396
397     /* test on strlen(tx) > 1 to remove case 'e' */
398     if ((int)strlen(tx) < 2)
399     {
400         if (ierrDouble == STRINGTODOUBLE_NO_ERROR)
401         {
402             ierr = (stringToComplexError) ierrDouble;
403         }
404         else
405         {
406             if (bConvertByNAN)
407             {
408                 ierrDouble = STRINGTODOUBLE_NOT_A_NUMBER;
409                 *real = returnNAN();
410                 *imag = 0;
411             }
412             else
413             {
414                 *real = 0;
415                 *imag = 0;
416                 ierr = (stringToComplexError) ierrDouble;
417             }
418         }
419     }
420     else if (ierrDouble != STRINGTODOUBLE_NO_ERROR)
421     {
422         modifiedTxt = strsub((char*)tx, ComplexScilab, ComplexI);
423         lnum = ParseNumber(modifiedTxt);
424         if (lnum <= 1)
425         {
426             /* manages special cases nan + nani, ... */
427             if (strnicmp(modifiedTxt, NanString, strlen(NanString)) == 0)
428             {
429                 lnum = strlen(NanString);
430             }
431             else if (strnicmp(modifiedTxt, InfString, strlen(InfString)) == 0)
432             {
433                 lnum = strlen(InfString);
434             }
435             else if (strnicmp(modifiedTxt, NegInfString, strlen(NegInfString)) == 0)
436             {
437                 lnum = strlen(NegInfString);
438             }
439             else if (strnicmp(modifiedTxt, PosInfString, strlen(PosInfString)) == 0)
440             {
441                 lnum = strlen(PosInfString);
442             }
443             else if (strnicmp(modifiedTxt, NegNanString, strlen(NegNanString)) == 0)
444             {
445                 lnum = strlen(NegNanString);
446             }
447             else if (strnicmp(modifiedTxt, PosNanString, strlen(PosNanString)) == 0)
448             {
449                 lnum = strlen(PosNanString);
450             }
451         }
452         inum_string = midstring(modifiedTxt, lnum, -1);
453
454         if ((inum_string[strlen(inum_string) - 1] == 'i') ||
455                 (inum_string[strlen(inum_string) - 1] == 'j')) // The imaginary part looks like "a*%i"
456         {
457             inum_string[strlen(inum_string) - 1] = 0;
458             if (inum_string[strlen(inum_string) - 1] == '*')
459             {
460                 inum_string[strlen(inum_string) - 1] = 0;
461             }
462
463             if (strcmp(inum_string, "+") == 0)
464             {
465                 FREE(inum_string);
466                 inum_string = os_strdup("+1");
467             }
468
469             if (strcmp(inum_string, "-") == 0)
470             {
471                 FREE(inum_string);
472                 inum_string = os_strdup("-1");
473             }
474             haveImagI = TRUE;
475         }
476         else if (inum_string[1] == 'i' || inum_string[1] == 'j') // The imaginary part looks like "%i*a". For instance if string() has been used
477         {
478             int len_inum_string = (int)strlen(inum_string);
479             for (i = 1; i < len_inum_string; ++i)
480             {
481                 inum_string[i] = inum_string[i + 1];    // Removing the "i"
482             }
483             if (inum_string[1] == '*')
484             {
485                 for (i = 1; i < len_inum_string; ++i)
486                 {
487                     inum_string[i] = inum_string[i + 1];    // Removing the "*"
488                 }
489             }
490
491             if (strcmp(inum_string, "+") == 0)
492             {
493                 FREE(inum_string);
494                 inum_string = os_strdup("+1");
495             }
496
497             if (strcmp(inum_string, "-") == 0)
498             {
499                 FREE(inum_string);
500                 inum_string = os_strdup("-1");
501             }
502             haveImagI = TRUE;
503         }
504         else
505         {
506             haveImagI = FALSE;
507         }
508         rnum_string = leftstring(modifiedTxt, lnum);
509
510         if (strcmp(inum_string, "") == 0)
511         {
512             *imag = stringToDouble(rnum_string, bConvertByNAN, &ierrDouble);
513             ierr = (stringToComplexError)(ierrDouble);
514             *real = 0.;
515         }
516         else
517         {
518             double dReal = 0.;
519             double dImag = 0.;
520
521             stringToDoubleError ierrReal = STRINGTODOUBLE_NO_ERROR;
522             stringToDoubleError ierrImag = STRINGTODOUBLE_NO_ERROR;
523             dReal = stringToDouble(rnum_string, FALSE, &ierrReal);
524             dImag = stringToDouble(inum_string, FALSE, &ierrImag);
525
526             if ((ierrReal == STRINGTODOUBLE_NO_ERROR) && (ierrImag == STRINGTODOUBLE_NO_ERROR))
527             {
528                 if (!haveImagI)
529                 {
530                     if (bConvertByNAN)
531                     {
532                         ierr = STRINGTOCOMPLEX_NO_ERROR;
533                         *real = returnNAN();
534                         *imag = 0.;
535                     }
536                     else
537                     {
538                         ierr = STRINGTOCOMPLEX_ERROR;
539                     }
540                 }
541                 else
542                 {
543                     ierr = STRINGTOCOMPLEX_NO_ERROR;
544                     *real = dReal;
545                     *imag = dImag;
546                 }
547             }
548             else
549             {
550                 if (bConvertByNAN)
551                 {
552                     ierr = STRINGTOCOMPLEX_NO_ERROR;
553                     *real = returnNAN();
554                     *imag = 0.;
555                 }
556                 else
557                 {
558                     ierr = STRINGTOCOMPLEX_ERROR;
559                 }
560             }
561         }
562
563         FREE(rnum_string);
564         FREE(inum_string);
565         FREE(modifiedTxt);
566     }
567     return ierr;
568 }
569 /* ========================================================================== */
570 static stringToComplexError ParseComplexValueW(const wchar_t *tx, BOOL bConvertByNAN, double *real, double *imag)
571 {
572     stringToDoubleError ierrDouble = STRINGTODOUBLE_NO_ERROR;
573     stringToComplexError ierr = STRINGTOCOMPLEX_NO_ERROR;
574     wchar_t *rnum_string = NULL;
575     wchar_t *inum_string = NULL;
576     size_t lnum = 0;
577     BOOL haveImagI = FALSE;
578     wchar_t *modifiedTxt = NULL;
579
580     *real = stringToDoubleW(tx, FALSE, &ierrDouble);
581     *imag = 0;
582
583     /* test on strlen(tx) > 1 to remove case 'e' */
584     if ((int)wcslen(tx) < 2)
585     {
586         if (ierrDouble == STRINGTODOUBLE_NO_ERROR)
587         {
588             ierr = (stringToComplexError) ierrDouble;
589         }
590         else
591         {
592             if (bConvertByNAN)
593             {
594                 ierrDouble = STRINGTODOUBLE_NOT_A_NUMBER;
595                 *real = returnNAN();
596                 *imag = 0;
597             }
598             else
599             {
600                 *real = 0;
601                 *imag = 0;
602                 ierr = (stringToComplexError) ierrDouble;
603             }
604         }
605     }
606     else if (ierrDouble != STRINGTODOUBLE_NO_ERROR)
607     {
608         modifiedTxt = wcssub(tx, ComplexScilabW, ComplexIW);
609         lnum = ParseNumberW(modifiedTxt);
610         if (lnum <= 1)
611         {
612             /* manages special cases nan + nani, ... */
613             if (wcsnicmp(modifiedTxt, NanStringW, wcslen(NanStringW)) == 0)
614             {
615                 lnum = wcslen(NanStringW);
616             }
617             else if (wcsnicmp(modifiedTxt, InfStringW, wcslen(InfStringW)) == 0)
618             {
619                 lnum = wcslen(InfStringW);
620             }
621             else if (wcsnicmp(modifiedTxt, NegInfStringW, wcslen(NegInfStringW)) == 0)
622             {
623                 lnum = wcslen(NegInfStringW);
624             }
625             else if (wcsnicmp(modifiedTxt, PosInfStringW, wcslen(PosInfStringW)) == 0)
626             {
627                 lnum = wcslen(PosInfStringW);
628             }
629             else if (wcsnicmp(modifiedTxt, NegNanStringW, wcslen(NegNanStringW)) == 0)
630             {
631                 lnum = wcslen(NegNanStringW);
632             }
633             else if (wcsnicmp(modifiedTxt, PosNanStringW, wcslen(PosNanStringW)) == 0)
634             {
635                 lnum = wcslen(PosNanStringW);
636             }
637             else if (wcsnicmp(modifiedTxt, ScilabEpsStringW, wcslen(ScilabEpsStringW)) == 0)
638             {
639                 lnum = wcslen(ScilabEpsStringW);
640             }
641             else if (wcsnicmp(modifiedTxt, ScilabPosEpsStringW, wcslen(ScilabPosEpsStringW)) == 0)
642             {
643                 lnum = wcslen(ScilabPosEpsStringW);
644             }
645             else if (wcsnicmp(modifiedTxt, ScilabNegEpsStringW, wcslen(ScilabNegEpsStringW)) == 0)
646             {
647                 lnum = wcslen(ScilabNegEpsStringW);
648             }
649             else if (wcsnicmp(modifiedTxt, ScilabPiStringW, wcslen(ScilabPiStringW)) == 0)
650             {
651                 lnum = wcslen(ScilabPiStringW);
652             }
653             else if (wcsnicmp(modifiedTxt, ScilabNegPiStringW, wcslen(ScilabNegPiStringW)) == 0)
654             {
655                 lnum = wcslen(ScilabNegPiStringW);
656             }
657             else if (wcsnicmp(modifiedTxt, ScilabPosPiStringW, wcslen(ScilabPosPiStringW)) == 0)
658             {
659                 lnum = wcslen(ScilabPosPiStringW);
660             }
661             else if (wcsnicmp(modifiedTxt, ScilabEStringW, wcslen(ScilabEStringW)) == 0)
662             {
663                 lnum = wcslen(ScilabEStringW);
664             }
665             else if (wcsnicmp(modifiedTxt, ScilabPosEStringW, wcslen(ScilabPosEStringW)) == 0)
666             {
667                 lnum = wcslen(ScilabPosEStringW);
668             }
669             else if (wcsnicmp(modifiedTxt, ScilabNegEStringW, wcslen(ScilabNegEStringW)) == 0)
670             {
671                 lnum = wcslen(ScilabNegEStringW);
672             }
673         }
674         inum_string = midstringW(modifiedTxt, lnum, -1);
675
676         if ((inum_string[wcslen(inum_string) - 1] == L'i') ||
677                 (inum_string[wcslen(inum_string) - 1] == L'j'))
678         {
679             inum_string[wcslen(inum_string) - 1] = 0;
680             if (inum_string[wcslen(inum_string) - 1] == L'*')
681             {
682                 inum_string[wcslen(inum_string) - 1] = 0;
683             }
684
685             if (wcscmp(inum_string, L"+") == 0)
686             {
687                 FREE(inum_string);
688                 inum_string = os_wcsdup(L"+1");
689             }
690
691             if (wcscmp(inum_string, L"-") == 0)
692             {
693                 FREE(inum_string);
694                 inum_string = os_wcsdup(L"-1");
695             }
696             haveImagI = TRUE;
697         }
698         else if ((inum_string[1] == L'i') ||
699                  (inum_string[1] == L'j'))
700         {
701             if (inum_string[2] == L'*')
702             {
703                 int i = 0;
704                 for (i = 1; (i + 2) < wcslen(inum_string); i++)
705                 {
706                     inum_string[i] = inum_string[i + 2];
707                 }
708                 inum_string[wcslen(inum_string) - 1] = 0;
709                 inum_string[wcslen(inum_string) - 1] = 0;
710             }
711
712             if (wcscmp(inum_string, L"+") == 0)
713             {
714                 FREE(inum_string);
715                 inum_string = os_wcsdup(L"+1");
716             }
717
718             if (wcscmp(inum_string, L"-") == 0)
719             {
720                 FREE(inum_string);
721                 inum_string = os_wcsdup(L"-1");
722             }
723             haveImagI = TRUE;
724         }
725         else
726         {
727             haveImagI = FALSE;
728         }
729         rnum_string = leftstringW(modifiedTxt, lnum);
730
731         if (wcscmp(inum_string, L"") == 0)
732         {
733             *imag = stringToDoubleW(rnum_string, bConvertByNAN, &ierrDouble);
734             ierr = (stringToComplexError)(ierrDouble);
735             *real = 0.;
736         }
737         else
738         {
739             double dReal = 0.;
740             double dImag = 0.;
741
742             stringToDoubleError ierrReal = STRINGTODOUBLE_NO_ERROR;
743             stringToDoubleError ierrImag = STRINGTODOUBLE_NO_ERROR;
744             dReal = stringToDoubleW(rnum_string, FALSE, &ierrReal);
745             dImag = stringToDoubleW(inum_string, FALSE, &ierrImag);
746
747             if ((ierrReal == STRINGTODOUBLE_NO_ERROR) && (ierrImag == STRINGTODOUBLE_NO_ERROR))
748             {
749                 if (!haveImagI)
750                 {
751                     if (bConvertByNAN)
752                     {
753                         ierr = STRINGTOCOMPLEX_NO_ERROR;
754                         *real = returnNAN();
755                         *imag = 0.;
756                     }
757                     else
758                     {
759                         ierr = STRINGTOCOMPLEX_ERROR;
760                     }
761                 }
762                 else
763                 {
764                     ierr = STRINGTOCOMPLEX_NO_ERROR;
765                     *real = dReal;
766                     *imag = dImag;
767                 }
768             }
769             else
770             {
771                 if (bConvertByNAN)
772                 {
773                     ierr = STRINGTOCOMPLEX_NO_ERROR;
774                     *real = returnNAN();
775                     *imag = 0.;
776                 }
777                 else
778                 {
779                     ierr = STRINGTOCOMPLEX_ERROR;
780                 }
781             }
782         }
783
784         if (rnum_string)
785         {
786             FREE(rnum_string);
787             rnum_string = NULL;
788         }
789         if (inum_string)
790         {
791             FREE(inum_string);
792             inum_string = NULL;
793         }
794         if (modifiedTxt)
795         {
796             FREE(modifiedTxt);
797             modifiedTxt = NULL;
798         }
799     }
800     return ierr;
801 }
802 /* ========================================================================== */
803 static char *midstring(const char *tx, size_t pos, int nb)
804 {
805     char *returnString = NULL;
806     if (tx)
807     {
808         int lenTx = (int) strlen(tx);
809         int posEnd = 0;
810         int newLen = 0;
811
812         if (nb < 0)
813         {
814             posEnd = lenTx;
815         }
816         else
817         {
818             posEnd = nb;
819         }
820         newLen = posEnd + 1;
821         if (newLen > 0)
822         {
823             returnString = (char*)MALLOC(sizeof(char) * newLen);
824             strncpy(returnString, &tx[pos], posEnd);
825             returnString[posEnd] = 0;
826         }
827     }
828     return returnString;
829 }
830 /* ========================================================================== */
831 static wchar_t* midstringW(const wchar_t* tx, size_t pos, int nb)
832 {
833     wchar_t *returnString = NULL;
834     if (tx)
835     {
836         int lenTx = (int) wcslen(tx);
837         int posEnd = 0;
838         int newLen = 0;
839
840         if (nb < 0)
841         {
842             posEnd = lenTx;
843         }
844         else
845         {
846             posEnd = nb;
847         }
848         newLen = posEnd + 1;
849         if (newLen > 0)
850         {
851             returnString = (wchar_t*)MALLOC(sizeof(wchar_t) * newLen);
852             wcsncpy(returnString, &tx[pos], posEnd);
853             returnString[posEnd] = 0;
854         }
855     }
856     return returnString;
857 }
858 /* ========================================================================== */
859 static char *leftstring(const char *tx, size_t pos)
860 {
861     char *returnString = NULL;
862     if (tx)
863     {
864         int lenTx = (int) strlen(tx);
865         returnString = os_strdup(tx);
866         if (pos > lenTx)
867         {
868             return returnString;
869         }
870         else
871         {
872             returnString[pos] = 0;
873         }
874     }
875     return returnString;
876 }
877 /* ========================================================================== */
878 static wchar_t *leftstringW(const wchar_t *tx, size_t pos)
879 {
880     wchar_t *returnString = NULL;
881     if (tx)
882     {
883         int lenTx = (int) wcslen(tx);
884         returnString = os_wcsdup(tx);
885         if (pos > lenTx)
886         {
887             return returnString;
888         }
889         else
890         {
891             returnString[pos] = 0;
892         }
893     }
894     return returnString;
895 }
896 /* ========================================================================== */
897 static BOOL is_unit_imaginary (const char *src, double *im)
898 {
899     char *modifiedSrc = strsub((char*)src, ComplexScilab, ComplexI);
900     char *nextChar = NULL;
901     BOOL isUnitImag = FALSE;
902
903     if (modifiedSrc == NULL)
904     {
905         return isUnitImag;
906     }
907
908     if (modifiedSrc[0] == LessChar)
909     {
910         *im = -1.0;
911         nextChar = modifiedSrc + 1;
912     }
913     else
914     {
915         *im = +1.0;
916         if (modifiedSrc[0] == PlusChar)
917         {
918             nextChar = modifiedSrc + 1;
919         }
920         else
921         {
922             nextChar = modifiedSrc;
923         }
924     }
925
926     if (nextChar)
927     {
928         if ((nextChar[0] == ComplexCharI || nextChar[0] == ComplexCharJ) && nextChar[1] == 0)
929         {
930             isUnitImag = TRUE;
931         }
932     }
933
934     if (modifiedSrc)
935     {
936         FREE(modifiedSrc);
937         modifiedSrc = NULL;
938     }
939     return isUnitImag;
940 }
941 /* ========================================================================== */
942 static BOOL is_unit_imaginaryW(const wchar_t *src, double *im)
943 {
944     wchar_t *modifiedSrc = wcssub(src, ComplexScilabW, ComplexIW);
945     wchar_t *nextChar = NULL;
946     BOOL isUnitImag = FALSE;
947
948     if (modifiedSrc == NULL)
949     {
950         return isUnitImag;
951     }
952
953     if (modifiedSrc[0] == LessChar)
954     {
955         *im = -1.0;
956         nextChar = modifiedSrc + 1;
957     }
958     else
959     {
960         *im = +1.0;
961         if (modifiedSrc[0] == PlusChar)
962         {
963             nextChar = modifiedSrc + 1;
964         }
965         else
966         {
967             nextChar = modifiedSrc;
968         }
969     }
970
971     if (nextChar)
972     {
973         if ((nextChar[0] == ComplexCharI || nextChar[0] == ComplexCharJ) && nextChar[1] == 0)
974         {
975             isUnitImag = TRUE;
976         }
977     }
978
979     if (modifiedSrc)
980     {
981         FREE(modifiedSrc);
982         modifiedSrc = NULL;
983     }
984     return isUnitImag;
985 }
986 /* ========================================================================== */
987 static double returnNAN(void)
988 {
989     static int first = 1;
990     static double nan = 1.0;
991
992     if ( first )
993     {
994         nan = (nan - (double) first) / (nan - (double) first);
995         first = 0;
996     }
997     return (nan);
998 }
999 // =============================================================================