mprintf fixed about new line
[scilab.git] / scilab / modules / output_stream / src / cpp / scilab_sprintf.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2013 - Scilab Enterprises - Calixte DENIZET
4  *  Copyright (C) 2013 - Scilab Enterprises - Cedric Delamarre
5  *  Copyright (C) 2015 - Scilab Enterprises - Antoine ELIAS
6  *
7  *  This file must be used under the terms of the CeCILL.
8  *  This source file is licensed as described in the file COPYING, which
9  *  you should have received as part of this distribution.  The terms
10  *  are also available at
11  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
12  *
13  */
14
15 #include <stdio.h>
16 #include <cmath>
17 #include <list>
18 #include "types.hxx"
19 #include "double.hxx"
20 #include "string.hxx"
21 #include "scilab_sprintf.hxx"
22
23 using namespace types;
24
25 extern "C"
26 {
27 #include "Scierror.h"
28 #include "sci_malloc.h"
29 #include "localization.h"
30 #include "charEncoding.h"
31 #include "os_string.h"
32 #include "os_wtoi.h"
33 #include "os_string.h"
34 }
35
36 static wchar_t* replaceAndCountLines(const wchar_t* _pwstInput, int* _piLines, int* _piNewLine);
37 static wchar_t* addl(TokenDef* token);
38 static void updatel(TokenDef* token);
39
40 #define NanString L"Nan"
41 #define InfString L"Inf"
42 #define NegInfString L"-Inf"
43
44 wchar_t** scilab_sprintf(const std::string& funcname, const wchar_t* _pwstInput, typed_list &in, int* _piOutputRows, int* _piNewLine)
45 {
46     /* Force Windows display to have two-digit exponent. */
47 #ifdef _MSC_VER
48     _set_output_format(_TWO_DIGIT_EXPONENT);
49 #endif
50     wchar_t** pwstOutput = nullptr;
51     int rhs = in.size();
52     wchar_t* pwstFirstOutput = nullptr;
53     *_piNewLine = 0;
54     int col = 0;
55
56     int first = 1;
57     if (funcname == "mfprintf")
58     {
59         first = 2;
60     }
61
62     //compute couple (index in input and col number ).
63     std::list<std::pair<int, int> > inPos;
64     for (int i = first; i < in.size(); ++i)
65     {
66         GenericType* gt = in[i]->getAs<GenericType>();
67         int col = gt->getCols();
68         for (int j = 0; j < col; ++j)
69         {
70             inPos.emplace_back(i, j);
71         }
72     }
73
74     std::list<std::pair<int, int> >::iterator itPos = inPos.begin();
75
76     //\n \n\r \r \t to string
77     //find number of lines
78     // replace \\n \\t... by \n \t...
79     pwstFirstOutput = replaceAndCountLines(_pwstInput, _piOutputRows, _piNewLine);
80
81     std::list<TokenDef*> token;
82
83     size_t start = 0;
84     size_t end = 0;
85     bool finish = false;
86
87     wchar_t* pwstStart = pwstFirstOutput;
88     bool percentpercent = false;
89
90     while (finish == false)
91     {
92         wchar_t* pwstEnd = wcsstr(pwstStart + (token.size() == 0 ? 0 : 1), L"%");
93         start = pwstStart - pwstFirstOutput;
94         percentpercent = false;
95         if (pwstEnd != nullptr)
96         {
97             if (token.size() && pwstStart[1] == L'%')
98             {
99                 //manage "%%"
100                 pwstEnd = wcsstr(pwstEnd + 1, L"%");
101                 if (pwstEnd == nullptr)
102                 {
103                     //end of string
104                     end = wcslen(pwstFirstOutput);
105                     finish = true;
106                 }
107                 else
108                 {
109                     end = pwstEnd - pwstFirstOutput;
110                 }
111
112                 // skip the first %
113                 start++;
114                 percentpercent = true;
115             }
116             else
117             {
118                 end = pwstEnd - pwstFirstOutput;
119             }
120         }
121         else
122         {
123             //end of string
124             end = wcslen(pwstFirstOutput);
125             finish = true;
126         }
127
128         TokenDef* tok = new TokenDef;
129         tok->pwstToken = new wchar_t[end - start + 1];
130         wcsncpy(tok->pwstToken, pwstFirstOutput + start, end - start);
131         tok->pwstToken[end - start] = L'\0';
132         token.push_back(tok);
133
134         wchar_t* pwstPercent = wcsstr(tok->pwstToken, L"%");
135         if (pwstPercent != nullptr && percentpercent == false)
136         {
137             //looking for flags
138             if (*(pwstPercent + 1) == L'-' ||
139                     *(pwstPercent + 1) == L'+' ||
140                     *(pwstPercent + 1) == L' ' ||
141                     *(pwstPercent + 1) == L'#' ||
142                     *(pwstPercent + 1) == L'0')
143             {
144                 pwstPercent++;
145             }
146
147             //looking for width
148             if (*(pwstPercent + 1) == L'*')
149             {
150                 if (itPos == inPos.end())
151                 {
152                     Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
153                     *_piOutputRows = 0;
154                     return nullptr;
155                 }
156
157                 int p = (*itPos).first;
158                 //input data use to set width
159                 if (in[p]->getId() != InternalType::IdScalarDouble)
160                 {
161                     Scierror(999, _("%s: Wrong type of input arguments #%d: A real scalar expected.\n"), funcname.data(), p);
162                     *_piOutputRows = 0;
163                     return nullptr;
164                 }
165
166
167                 Double* dbl = in[p]->getAs<Double>();
168                 tok->width = static_cast<int>(dbl->get()[0]);
169                 tok->widthStar = true;
170                 ++itPos;
171                 ++pwstPercent;
172             }
173             else
174             {
175                 //number
176                 if (iswdigit(*(pwstPercent + 1)))
177                 {
178                     tok->width = os_wtoi(pwstPercent + 1);
179                     while (iswdigit(*(pwstPercent + 1)))
180                     {
181                         pwstPercent++;
182                     }
183                 }
184             }
185
186             //looking for precision
187             if (*(pwstPercent + 1) == L'.')
188             {
189                 pwstPercent++;
190
191                 if (iswdigit(*(pwstPercent + 1)))
192                 {
193                     tok->prec = os_wtoi(pwstPercent + 1);
194                     while (iswdigit(*(pwstPercent + 1)))
195                     {
196                         pwstPercent++;
197                     }
198                 }
199                 else if (*(pwstPercent + 1) == L'*')
200                 {
201                     if (itPos == inPos.end())
202                     {
203                         Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
204                         *_piOutputRows = 0;
205                         return nullptr;
206                     }
207
208                     int p = (*itPos).first;
209                     //input data use to set prec
210                     if (in[p]->getId() != InternalType::IdScalarDouble)
211                     {
212                         Scierror(999, _("%s: Wrong type of input arguments #%d: A real scalar expected.\n"), funcname.data(), p + 1);
213                         *_piOutputRows = 0;
214                         return nullptr;
215                     }
216
217                     Double* dbl = in[p]->getAs<Double>();
218                     tok->prec = static_cast<int>(dbl->get()[0]);
219                     tok->precStar = true;
220                     ++itPos;
221                     ++pwstPercent;
222                 }
223             }
224
225             //looking for length
226             if (*(pwstPercent + 1) == L'h' ||
227                     *(pwstPercent + 1) == L'l' ||
228                     *(pwstPercent + 1) == L'L')
229             {
230                 tok->length = true;
231                 pwstPercent++;
232             }
233
234             wchar_t wcType = *(pwstPercent + 1);
235             tok->typePos = (pwstPercent + 1) - tok->pwstToken;
236
237             switch (wcType)
238             {
239                 case L'i': //integer
240                 case L'd': //integer
241                 {
242                     if (itPos == inPos.end())
243                     {
244                         FREE(pwstFirstOutput);
245                         Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
246                         *_piOutputRows = 0;
247                         return nullptr;
248                     }
249
250                     int p = (*itPos).first;
251                     int c = (*itPos).second;
252                     if (in[p]->getType() != InternalType::ScilabDouble)
253                     {
254                         FREE(pwstFirstOutput);
255                         Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
256                         *_piOutputRows = 0;
257                         return nullptr;
258                     }
259
260                     tok->outputType = InternalType::ScilabInt32;
261                     tok->pos = p;
262                     tok->col = c;
263                     ++itPos;
264                     break;
265                 }
266                 case L'o': //octal
267                 case L'u': //unsigned
268                 case L'x': //hex
269                 case L'X': //HEX
270                 {
271                     if (itPos == inPos.end())
272                     {
273                         FREE(pwstFirstOutput);
274                         Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
275                         *_piOutputRows = 0;
276                         return nullptr;
277                     }
278
279                     int p = (*itPos).first;
280                     int c = (*itPos).second;
281                     if (in[p]->getType() != InternalType::ScilabDouble)
282                     {
283                         FREE(pwstFirstOutput);
284                         Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
285                         *_piOutputRows = 0;
286                         return nullptr;
287                     }
288
289                     tok->outputType = InternalType::ScilabUInt32;
290                     tok->pos = p;
291                     tok->col = c;
292                     ++itPos;
293                     break;
294                 }
295                 case L'f': //float
296                 case L'e': //exp
297                 case L'E': //EXP
298                 case L'g': //shorter between float or exp
299                 case L'G': //shorter between float or EXP
300                 {
301                     if (itPos == inPos.end())
302                     {
303                         FREE(pwstFirstOutput);
304                         Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
305                         *_piOutputRows = 0;
306                         return nullptr;
307                     }
308
309                     int p = (*itPos).first;
310                     int c = (*itPos).second;
311                     if (in[p]->getType() != InternalType::ScilabDouble)
312                     {
313                         FREE(pwstFirstOutput);
314                         Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
315                         *_piOutputRows = 0;
316                         return nullptr;
317                     }
318
319                     tok->outputType = InternalType::ScilabDouble;
320                     tok->pos = p;
321                     tok->col = c;
322                     ++itPos;
323                     break;
324                 }
325                 case L's':
326                 case L'c':
327                 {
328                     if (itPos == inPos.end())
329                     {
330                         FREE(pwstFirstOutput);
331                         Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
332                         *_piOutputRows = 0;
333                         return nullptr;
334                     }
335
336                     int p = (*itPos).first;
337                     int c = (*itPos).second;
338                     if (in[p]->getType() != InternalType::ScilabString)
339                     {
340                         FREE(pwstFirstOutput);
341                         Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
342                         *_piOutputRows = 0;
343                         return nullptr;
344                     }
345
346                     if (tok->length == false)
347                     {
348                         updatel(tok);
349                     }
350
351                     tok->outputType = InternalType::ScilabString;
352                     tok->pos = p;
353                     tok->col = c;
354                     ++itPos;
355                     break;
356                 }
357                 default:
358                     FREE(pwstFirstOutput);
359                     Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
360                     *_piOutputRows = 0;
361                     return nullptr;
362                     break;
363             }
364         }
365
366         //continue
367         pwstStart = pwstEnd;
368     }
369
370     FREE(pwstFirstOutput);
371     pwstFirstOutput = nullptr;
372
373     int iLoop = 1;
374     if (token.size() > 1)
375     {
376         std::list<TokenDef*>::iterator it = std::next(token.begin());
377         iLoop = in[(*it)->pos]->getAs<GenericType>()->getRows();
378         for (; it != token.end(); ++it)
379         {
380             iLoop = std::min(iLoop, in[(*it)->pos]->getAs<GenericType>()->getRows());
381         }
382
383         if (*_piNewLine || (*_piOutputRows) > 1)
384         {
385             (*_piOutputRows) *= iLoop;
386         }
387     }
388
389
390     //if ((token.size() - 1) != inPos.size())
391     //{
392     //    Scierror(999, _("%s: Wrong number of input arguments: at most %d expected.\n"), funcname.data(), token.size() - 1);
393     //    *_piOutputRows = 0;
394     //    return nullptr;
395     //}
396
397     std::wostringstream oFirstOutput;
398     for (int j = 0; j < iLoop; j++)
399     {
400         //copy the 0th token
401         TokenDef* f = token.front();
402         oFirstOutput << f->pwstToken;
403
404         //start at 1, the 0th is always without %
405         std::list<TokenDef*>::iterator it = std::next(token.begin());
406         for (; it != token.end(); ++it)
407         {
408             TokenDef* tok = *it;
409             switch (tok->outputType)
410             {
411                 case InternalType::ScilabDouble:
412                 {
413                     wchar_t pwstTemp[bsiz];
414                     double dblVal = in[tok->pos]->getAs<Double>()->get(j, tok->col);
415
416                     if (std::isfinite(dblVal))
417                     {
418                         if (tok->widthStar)
419                         {
420                             if (tok->precStar)
421                             {
422                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->width, tok->prec, dblVal);
423                             }
424                             else
425                             {
426                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->width, dblVal);
427                             }
428                         }
429                         else
430                         {
431                             if (tok->precStar)
432                             {
433                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->prec, dblVal);
434                             }
435                             else
436                             {
437                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, dblVal);
438                             }
439                         }
440                     }
441                     else
442                     {
443                         wchar_t* newToken = addl(tok);
444
445                         if (std::isnan(dblVal))
446                         {
447                             os_swprintf(pwstTemp, bsiz, newToken, NanString);
448                         }
449                         else if (std::signbit(dblVal))
450                         {
451                             os_swprintf(pwstTemp, bsiz, newToken, NegInfString);
452                         }
453                         else
454                         {
455                             os_swprintf(pwstTemp, bsiz, newToken, InfString);
456                         }
457
458                         delete[] newToken;
459                     }
460
461                     oFirstOutput << pwstTemp;
462                     break;
463                 }
464                 case InternalType::ScilabInt32:
465                 {
466                     wchar_t pwstTemp[bsiz];
467                     double dblVal = in[tok->pos]->getAs<Double>()->get(j, tok->col);
468                     int iVal = (int)dblVal;
469                     if (std::isfinite(dblVal))
470                     {
471                         if (tok->widthStar)
472                         {
473                             if (tok->precStar)
474                             {
475                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->width, tok->prec, iVal);
476                             }
477                             else
478                             {
479                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->width, iVal);
480                             }
481                         }
482                         else
483                         {
484                             if (tok->precStar)
485                             {
486                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->prec, iVal);
487                             }
488                             else
489                             {
490                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, iVal);
491                             }
492                         }
493                     }
494                     else
495                     {
496                         wchar_t* newToken = addl(tok);
497
498                         if (std::isnan(dblVal))
499                         {
500                             os_swprintf(pwstTemp, bsiz, newToken, NanString);
501                         }
502                         else
503                         {
504                             if (std::signbit(dblVal))
505                             {
506                                 os_swprintf(pwstTemp, bsiz, newToken, NegInfString);
507                             }
508                             else
509                             {
510                                 os_swprintf(pwstTemp, bsiz, newToken, InfString);
511                             }
512                         }
513
514                         delete[] newToken;
515                     }
516
517                     oFirstOutput << pwstTemp;
518                     break;
519                 }
520                 case InternalType::ScilabUInt32:
521                 {
522                     wchar_t pwstTemp[bsiz];
523                     double dblVal = in[tok->pos]->getAs<Double>()->get(j, tok->col);
524                     unsigned int iVal = (unsigned int)dblVal;
525
526                     if (std::isfinite(dblVal))
527                     {
528                         if (tok->widthStar)
529                         {
530                             if (tok->precStar)
531                             {
532                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->width, tok->prec, iVal);
533                             }
534                             else
535                             {
536                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->width, iVal);
537                             }
538                         }
539                         else
540                         {
541                             if (tok->precStar)
542                             {
543                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->prec, iVal);
544                             }
545                             else
546                             {
547                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, iVal);
548                             }
549                         }
550                     }
551                     else
552                     {
553                         wchar_t* newToken = addl(tok);
554
555                         if (std::isnan(dblVal))
556                         {
557                             os_swprintf(pwstTemp, bsiz, newToken, NanString);
558                         }
559                         else
560                         {
561                             if (std::signbit(dblVal))
562                             {
563                                 os_swprintf(pwstTemp, bsiz, newToken, NegInfString);
564                             }
565                             else
566                             {
567                                 os_swprintf(pwstTemp, bsiz, newToken, InfString);
568                             }
569                         }
570
571                         delete[] newToken;
572                     }
573
574                     oFirstOutput << pwstTemp;
575                     break;
576                 }
577                 case InternalType::ScilabString:
578                 {
579                     wchar_t* pwstStr = nullptr;
580                     std::wstring NaN = NanString;
581                     std::wstring nInf = NegInfString;
582                     std::wstring pInf = InfString;
583
584                     InternalType* it = in[tok->pos];
585                     if (it->isDouble() && std::isnan(it->getAs<types::Double>()->get(0)))
586                     {
587                         pwstStr = const_cast<wchar_t*>(NaN.c_str());
588                     }
589                     else if (it->isDouble() && std::isfinite(it->getAs<types::Double>()->get(0)) == false)
590                     {
591                         if (std::signbit(it->getAs<types::Double>()->get(0)))
592                         {
593                             pwstStr = const_cast<wchar_t*>(nInf.c_str());
594                         }
595                         else
596                         {
597                             pwstStr = const_cast<wchar_t*>(pInf.c_str());
598                         }
599                     }
600                     else
601                     {
602                         pwstStr = it->getAs<types::String>()->get(j, tok->col);
603                     }
604
605                     int posC = (int)wcscspn(tok->pwstToken, L"c");
606                     int posS = (int)wcscspn(tok->pwstToken, L"s");
607
608                     if (posS == 0 || posC == 0)
609                     {
610                         *_piOutputRows = 0;
611                         return nullptr;
612                     }
613
614                     bool bC = posC < posS;
615                     int len = 1;
616                     if (tok->prec)
617                     {
618                         if (bC == false)
619                         {
620                             len = std::min(std::abs(tok->prec), (int)wcslen(pwstStr));
621                         }
622                     }
623                     else
624                     {
625                         if (bC == false)
626                         {
627                             len = (int)wcslen(pwstStr);
628                         }
629                     }
630
631                     int tokenLen = (int)wcslen(tok->pwstToken);
632                     len += tokenLen;
633                     len = std::max(len, std::abs(tok->width));
634                     //add len of string after token like "%20s>>>" add space for ">>>"
635                     len += (tokenLen - (bC ? posC : posS));
636                     wchar_t* pwstTemp = (wchar_t*)MALLOC((len + 1) * sizeof(wchar_t));
637
638                     if (bC)
639                     {
640                         if (tok->widthStar)
641                         {
642                             os_swprintf(pwstTemp, len + 1, tok->pwstToken, tok->width, pwstStr[0]);
643                         }
644                         else
645                         {
646                             os_swprintf(pwstTemp, len + 1, tok->pwstToken, pwstStr[0]);
647                         }
648                     }
649                     else
650                     {
651                         if (tok->widthStar)
652                         {
653                             os_swprintf(pwstTemp, len + 1, tok->pwstToken, tok->width, pwstStr);
654                         }
655                         else
656                         {
657                             os_swprintf(pwstTemp, len + 1, tok->pwstToken, pwstStr);
658                         }
659                     }
660
661                     oFirstOutput << pwstTemp;
662                     FREE(pwstTemp);
663                     break;
664                 }
665                 default:
666                     // management of %%
667                     oFirstOutput << tok->pwstToken;
668                     break;
669             }
670         }
671     }
672
673     pwstFirstOutput = os_wcsdup((wchar_t*)oFirstOutput.str().c_str());
674
675     for (auto & tok : token)
676     {
677         delete[] tok->pwstToken;
678         delete tok;
679     }
680
681     pwstOutput = (wchar_t**)MALLOC((*_piOutputRows) * sizeof(wchar_t*));
682
683     size_t iLen = wcslen(pwstFirstOutput);
684     int iStart = 0;
685     int j = 0;
686     for (int i = 0; i < iLen; i++)
687     {
688         if (pwstFirstOutput[i] == L'\n')
689         {
690             int iSize = i - iStart;
691             pwstOutput[j] = (wchar_t*)MALLOC(sizeof(wchar_t) * (iSize + 1));
692             wcsncpy(pwstOutput[j], pwstFirstOutput + iStart, iSize);
693             pwstOutput[j][iSize] = L'\0';
694             iStart = i + 1;
695             j++;
696         }
697     }
698
699     if (j == (*_piOutputRows) - 1)
700     {
701         pwstOutput[j] = os_wcsdup(pwstFirstOutput + iStart);
702     }
703
704     FREE(pwstFirstOutput);
705     return pwstOutput;
706 }
707 /*--------------------------------------------------------------------------*/
708 /*--------------------------------------------------------------------------*/
709 // replace "\\n" "\\r" "\\t" "\\r\\n" by '\n' '\r' '\t' '\n'
710 // count number of lines
711 // indicate if one '\n' is at the end of string
712 static wchar_t* replaceAndCountLines(const wchar_t* _pwstInput, int* _piLines, int* _piNewLine)
713 {
714     size_t iInputLen = wcslen(_pwstInput);
715     wchar_t* pwstFirstOutput = (wchar_t*)MALLOC(sizeof(wchar_t) * (iInputLen + 1));
716
717     int iPos = 0;
718     *_piLines = 1;
719
720     for (int i = 0; i < iInputLen; i++)
721     {
722         if (_pwstInput[i] == L'\\')
723         {
724             if (iInputLen == i + 1)
725             {
726                 continue;
727             }
728
729             switch (_pwstInput[i + 1])
730             {
731                 case L'n':
732                     pwstFirstOutput[iPos++] = L'\n';
733                     (*_piLines)++;
734                     i++;
735                     break;
736                 case L'r':
737                     if (iInputLen > i + 3 && _pwstInput[i + 2] == L'\\' && _pwstInput[i + 3] == L'n')
738                     {
739                         pwstFirstOutput[iPos++] = L'\n';
740                         (*_piLines)++;
741                         i += 3;
742                     }
743                     else
744                     {
745                         pwstFirstOutput[iPos++] = L'\r';
746                         i++;
747                     }
748                     break;
749                 case L't':
750                     pwstFirstOutput[iPos++] = L'\t';
751                     i++;
752                     break;
753                 case L'\\':
754                     pwstFirstOutput[iPos++] = L'\\';
755                     i++;
756                     break;
757                 default:
758                     break;
759             }
760         }
761         else if (_pwstInput[i] == 0x0A) // ascii(10) == "\n"
762         {
763             pwstFirstOutput[iPos++] = L'\n';
764             (*_piLines)++;
765         }
766         else
767         {
768             pwstFirstOutput[iPos++] = _pwstInput[i];
769         }
770     }
771
772     // do not count '\n' if it's at the end of string
773     // it will be manage by piNewLine
774     if (pwstFirstOutput[iPos - 1] == '\n')
775     {
776         (*_piLines)--;
777         (*_piNewLine) = 1;
778     }
779
780     pwstFirstOutput[iPos] = 0;
781     return pwstFirstOutput;
782 }
783 /*--------------------------------------------------------------------------*/
784 wchar_t* addl(TokenDef* token)
785 {
786     //replace %s or %c by %ls or %lc to wide char compatibility
787     int iPos = token->typePos;
788     int sizeTotal = (int)wcslen(token->pwstToken);
789     wchar_t* pwstToken = new wchar_t[sizeTotal + 2];
790
791     wcsncpy(pwstToken, token->pwstToken, iPos);
792     pwstToken[iPos] = L'l';
793     pwstToken[iPos + 1] = L's';
794     wcsncpy(&pwstToken[iPos + 2], token->pwstToken + iPos + 1, sizeTotal - (iPos + 1));
795     pwstToken[sizeTotal + 1] = L'\0';
796
797     return pwstToken;
798 }
799 /*--------------------------------------------------------------------------*/
800 void updatel(TokenDef* token)
801 {
802     wchar_t* newToken = addl(token);
803     delete[] token->pwstToken;
804     token->pwstToken = newToken;
805 }