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