fix some gcc 4.9 valid warnings
[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                         Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
245                         *_piOutputRows = 0;
246                         return nullptr;
247                     }
248
249                     int p = (*itPos).first;
250                     int c = (*itPos).second;
251                     if (in[p]->getType() != InternalType::ScilabDouble)
252                     {
253                         Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
254                         *_piOutputRows = 0;
255                         return nullptr;
256                     }
257
258                     tok->outputType = InternalType::ScilabInt32;
259                     tok->pos = p;
260                     tok->col = c;
261                     ++itPos;
262                     break;
263                 }
264                 case L'o': //octal
265                 case L'u': //unsigned
266                 case L'x': //hex
267                 case L'X': //HEX
268                 {
269                     if (itPos == inPos.end())
270                     {
271                         Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
272                         *_piOutputRows = 0;
273                         return nullptr;
274                     }
275
276                     int p = (*itPos).first;
277                     int c = (*itPos).second;
278                     if (in[p]->getType() != InternalType::ScilabDouble)
279                     {
280                         Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
281                         *_piOutputRows = 0;
282                         return nullptr;
283                     }
284
285                     tok->outputType = InternalType::ScilabUInt32;
286                     tok->pos = p;
287                     tok->col = c;
288                     ++itPos;
289                     break;
290                 }
291                 case L'f': //float
292                 case L'e': //exp
293                 case L'E': //EXP
294                 case L'g': //shorter between float or exp
295                 case L'G': //shorter between float or EXP
296                 {
297                     if (itPos == inPos.end())
298                     {
299                         Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
300                         *_piOutputRows = 0;
301                         return nullptr;
302                     }
303
304                     int p = (*itPos).first;
305                     int c = (*itPos).second;
306                     if (in[p]->getType() != InternalType::ScilabDouble)
307                     {
308                         Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
309                         *_piOutputRows = 0;
310                         return nullptr;
311                     }
312
313                     tok->outputType = InternalType::ScilabDouble;
314                     tok->pos = p;
315                     tok->col = c;
316                     ++itPos;
317                     break;
318                 }
319                 case L's':
320                 case L'c':
321                 {
322                     if (itPos == inPos.end())
323                     {
324                         Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
325                         *_piOutputRows = 0;
326                         return nullptr;
327                     }
328
329                     int p = (*itPos).first;
330                     int c = (*itPos).second;
331                     if (in[p]->getType() != InternalType::ScilabString)
332                     {
333                         Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
334                         *_piOutputRows = 0;
335                         return nullptr;
336                     }
337
338                     if (tok->length == false)
339                     {
340                         updatel(tok);
341                     }
342
343                     tok->outputType = InternalType::ScilabString;
344                     tok->pos = p;
345                     tok->col = c;
346                     ++itPos;
347                     break;
348                 }
349                 default:
350                     Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
351                     *_piOutputRows = 0;
352                     return nullptr;
353                     break;
354             }
355         }
356
357         //continue
358         pwstStart = pwstEnd;
359     }
360
361     FREE(pwstFirstOutput);
362     pwstFirstOutput = nullptr;
363
364     int iLoop = 1;
365     if (token.size() > 1)
366     {
367         std::list<TokenDef*>::iterator it = std::next(token.begin());
368         iLoop = in[(*it)->pos]->getAs<GenericType>()->getRows();
369         for (; it != token.end(); ++it)
370         {
371             iLoop = std::min(iLoop, in[(*it)->pos]->getAs<GenericType>()->getRows());
372         }
373
374         if (*_piNewLine || (*_piOutputRows) > 1)
375         {
376             (*_piOutputRows) *= iLoop;
377         }
378     }
379
380
381     //if ((token.size() - 1) != inPos.size())
382     //{
383     //    Scierror(999, _("%s: Wrong number of input arguments: at most %d expected.\n"), funcname.data(), token.size() - 1);
384     //    *_piOutputRows = 0;
385     //    return nullptr;
386     //}
387
388     std::wostringstream oFirstOutput;
389     for (int j = 0; j < iLoop; j++)
390     {
391         //copy the 0th token
392         TokenDef* f = token.front();
393         oFirstOutput << f->pwstToken;
394
395         //start at 1, the 0th is always without %
396         std::list<TokenDef*>::iterator it = std::next(token.begin());
397         for (; it != token.end(); ++it)
398         {
399             TokenDef* tok = *it;
400             switch (tok->outputType)
401             {
402                 case InternalType::ScilabDouble:
403                 {
404                     wchar_t pwstTemp[bsiz];
405                     double dblVal = in[tok->pos]->getAs<Double>()->get(j, tok->col);
406
407                     if (std::isfinite(dblVal))
408                     {
409                         if (tok->widthStar)
410                         {
411                             if (tok->precStar)
412                             {
413                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->width, tok->prec, dblVal);
414                             }
415                             else
416                             {
417                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->width, dblVal);
418                             }
419                         }
420                         else
421                         {
422                             if (tok->precStar)
423                             {
424                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->prec, dblVal);
425                             }
426                             else
427                             {
428                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, dblVal);
429                             }
430                         }
431                     }
432                     else
433                     {
434                         wchar_t* newToken = addl(tok);
435
436                         if (std::isnan(dblVal))
437                         {
438                             os_swprintf(pwstTemp, bsiz, newToken, NanString);
439                         }
440                         else if (std::signbit(dblVal))
441                         {
442                             os_swprintf(pwstTemp, bsiz, newToken, NegInfString);
443                         }
444                         else
445                         {
446                             os_swprintf(pwstTemp, bsiz, newToken, InfString);
447                         }
448
449                         delete[] newToken;
450                     }
451
452                     oFirstOutput << pwstTemp;
453                     break;
454                 }
455                 case InternalType::ScilabInt32:
456                 {
457                     wchar_t pwstTemp[bsiz];
458                     double dblVal = in[tok->pos]->getAs<Double>()->get(j, tok->col);
459                     int iVal = (int)dblVal;
460                     if (std::isfinite(dblVal))
461                     {
462                         if (tok->widthStar)
463                         {
464                             if (tok->precStar)
465                             {
466                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->width, tok->prec, iVal);
467                             }
468                             else
469                             {
470                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->width, iVal);
471                             }
472                         }
473                         else
474                         {
475                             if (tok->precStar)
476                             {
477                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->prec, iVal);
478                             }
479                             else
480                             {
481                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, iVal);
482                             }
483                         }
484                     }
485                     else
486                     {
487                         wchar_t* newToken = addl(tok);
488
489                         if (std::isnan(dblVal))
490                         {
491                             os_swprintf(pwstTemp, bsiz, newToken, NanString);
492                         }
493                         else
494                         {
495                             if (std::signbit(dblVal))
496                             {
497                                 os_swprintf(pwstTemp, bsiz, newToken, NegInfString);
498                             }
499                             else
500                             {
501                                 os_swprintf(pwstTemp, bsiz, newToken, InfString);
502                             }
503                         }
504
505                         delete[] newToken;
506                     }
507
508                     oFirstOutput << pwstTemp;
509                     break;
510                 }
511                 case InternalType::ScilabUInt32:
512                 {
513                     wchar_t pwstTemp[bsiz];
514                     double dblVal = in[tok->pos]->getAs<Double>()->get(j, tok->col);
515                     unsigned int iVal = (unsigned int)dblVal;
516
517                     if (std::isfinite(dblVal))
518                     {
519                         if (tok->widthStar)
520                         {
521                             if (tok->precStar)
522                             {
523                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->width, tok->prec, iVal);
524                             }
525                             else
526                             {
527                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->width, iVal);
528                             }
529                         }
530                         else
531                         {
532                             if (tok->precStar)
533                             {
534                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->prec, iVal);
535                             }
536                             else
537                             {
538                                 os_swprintf(pwstTemp, bsiz, tok->pwstToken, iVal);
539                             }
540                         }
541                     }
542                     else
543                     {
544                         wchar_t* newToken = addl(tok);
545
546                         if (std::isnan(dblVal))
547                         {
548                             os_swprintf(pwstTemp, bsiz, newToken, NanString);
549                         }
550                         else
551                         {
552                             if (std::signbit(dblVal))
553                             {
554                                 os_swprintf(pwstTemp, bsiz, newToken, NegInfString);
555                             }
556                             else
557                             {
558                                 os_swprintf(pwstTemp, bsiz, newToken, InfString);
559                             }
560                         }
561
562                         delete[] newToken;
563                     }
564
565                     oFirstOutput << pwstTemp;
566                     break;
567                 }
568                 case InternalType::ScilabString:
569                 {
570                     wchar_t* pwstStr = nullptr;
571                     std::wstring NaN = NanString;
572                     std::wstring nInf = NegInfString;
573                     std::wstring pInf = InfString;
574
575                     InternalType* it = in[tok->pos];
576                     if (it->isDouble() && std::isnan(it->getAs<types::Double>()->get(0)))
577                     {
578                         pwstStr = const_cast<wchar_t*>(NaN.c_str());
579                     }
580                     else if (it->isDouble() && std::isfinite(it->getAs<types::Double>()->get(0)) == false)
581                     {
582                         if (std::signbit(it->getAs<types::Double>()->get(0)))
583                         {
584                             pwstStr = const_cast<wchar_t*>(nInf.c_str());
585                         }
586                         else
587                         {
588                             pwstStr = const_cast<wchar_t*>(pInf.c_str());
589                         }
590                     }
591                     else
592                     {
593                         pwstStr = it->getAs<types::String>()->get(j, tok->col);
594                     }
595
596                     int posC = (int)wcscspn(tok->pwstToken, L"c");
597                     int posS = (int)wcscspn(tok->pwstToken, L"s");
598
599                     if (posS == 0 || posC == 0)
600                     {
601                         *_piOutputRows = 0;
602                         return nullptr;
603                     }
604
605                     bool bC = posC < posS;
606                     int len = 1;
607                     if (tok->prec)
608                     {
609                         if (bC == false)
610                         {
611                             len = std::min(std::abs(tok->prec), (int)wcslen(pwstStr));
612                         }
613                     }
614                     else
615                     {
616                         if (bC == false)
617                         {
618                             len = (int)wcslen(pwstStr);
619                         }
620                     }
621
622                     int tokenLen = (int)wcslen(tok->pwstToken);
623                     len += tokenLen;
624                     len = std::max(len, std::abs(tok->width));
625                     //add len of string after token like "%20s>>>" add space for ">>>"
626                     len += (tokenLen - (bC ? posC : posS));
627                     wchar_t* pwstTemp = (wchar_t*)MALLOC((len + 1) * sizeof(wchar_t));
628
629                     if (bC)
630                     {
631                         if (tok->widthStar)
632                         {
633                             os_swprintf(pwstTemp, len + 1, tok->pwstToken, tok->width, pwstStr[0]);
634                         }
635                         else
636                         {
637                             os_swprintf(pwstTemp, len + 1, tok->pwstToken, pwstStr[0]);
638                         }
639                     }
640                     else
641                     {
642                         if (tok->widthStar)
643                         {
644                             os_swprintf(pwstTemp, len + 1, tok->pwstToken, tok->width, pwstStr);
645                         }
646                         else
647                         {
648                             os_swprintf(pwstTemp, len + 1, tok->pwstToken, pwstStr);
649                         }
650                     }
651
652                     oFirstOutput << pwstTemp;
653                     FREE(pwstTemp);
654                     break;
655                 }
656                 default:
657                     // management of %%
658                     oFirstOutput << tok->pwstToken;
659                     break;
660             }
661         }
662     }
663
664     pwstFirstOutput = os_wcsdup((wchar_t*)oFirstOutput.str().c_str());
665
666     for (auto& tok : token)
667     {
668         delete[] tok->pwstToken;
669         delete tok;
670     }
671
672     pwstOutput = (wchar_t**)MALLOC((*_piOutputRows) * sizeof(wchar_t*));
673
674     size_t iLen = wcslen(pwstFirstOutput);
675     int iStart = 0;
676     int j = 0;
677     for (int i = 0; i < iLen; i++)
678     {
679         if (pwstFirstOutput[i] == L'\n')
680         {
681             int iSize = i - iStart;
682             pwstOutput[j] = (wchar_t*)MALLOC(sizeof(wchar_t) * (iSize + 1));
683             wcsncpy(pwstOutput[j], pwstFirstOutput + iStart, iSize);
684             pwstOutput[j][iSize] = L'\0';
685             iStart = i + 1;
686             j++;
687         }
688     }
689
690     if (j == (*_piOutputRows) - 1)
691     {
692         pwstOutput[j] = os_wcsdup(pwstFirstOutput + iStart);
693     }
694
695     FREE(pwstFirstOutput);
696     return pwstOutput;
697 }
698 /*--------------------------------------------------------------------------*/
699 /*--------------------------------------------------------------------------*/
700 // replace "\\n" "\\r" "\\t" "\\r\\n" by '\n' '\r' '\t' '\n'
701 // count number of lines
702 // indicate if one '\n' is at the end of string
703 static wchar_t* replaceAndCountLines(const wchar_t* _pwstInput, int* _piLines, int* _piNewLine)
704 {
705     size_t iInputLen = wcslen(_pwstInput);
706     wchar_t* pwstFirstOutput = (wchar_t*)MALLOC(sizeof(wchar_t) * (iInputLen + 1));
707
708     int iPos = 0;
709     *_piLines = 1;
710
711     for (int i = 0; i < iInputLen; i++)
712     {
713         if (_pwstInput[i] == L'\\')
714         {
715             if (iInputLen == i + 1)
716             {
717                 continue;
718             }
719
720             switch (_pwstInput[i + 1])
721             {
722                 case L'n':
723                     pwstFirstOutput[iPos++] = L'\n';
724                     (*_piLines)++;
725                     i++;
726                     break;
727                 case L'r':
728                     if (iInputLen > i + 3 && _pwstInput[i + 2] == L'\\' && _pwstInput[i + 3] == L'n')
729                     {
730                         pwstFirstOutput[iPos++] = L'\n';
731                         (*_piLines)++;
732                         i += 3;
733                     }
734                     else
735                     {
736                         pwstFirstOutput[iPos++] = L'\r';
737                         i++;
738                     }
739                     break;
740                 case L't':
741                     pwstFirstOutput[iPos++] = L'\t';
742                     i++;
743                     break;
744                 case L'\\':
745                     pwstFirstOutput[iPos++] = L'\\';
746                     i++;
747                     break;
748                 default:
749                     break;
750             }
751         }
752         else
753         {
754             pwstFirstOutput[iPos++] = _pwstInput[i];
755         }
756     }
757
758     // do not count '\n' if it's at the end of string
759     // it will be manage by piNewLine
760     if (pwstFirstOutput[iPos - 1] == '\n')
761     {
762         (*_piLines)--;
763         (*_piNewLine) = 1;
764     }
765
766     pwstFirstOutput[iPos] = 0;
767     return pwstFirstOutput;
768 }
769 /*--------------------------------------------------------------------------*/
770 wchar_t* addl(TokenDef* token)
771 {
772     //replace %s or %c by %ls or %lc to wide char compatibility
773     int iPos = token->typePos;
774     int sizeTotal = (int)wcslen(token->pwstToken);
775     wchar_t* pwstToken = new wchar_t[sizeTotal + 2];
776
777     wcsncpy(pwstToken, token->pwstToken, iPos);
778     pwstToken[iPos] = L'l';
779     pwstToken[iPos + 1] = L's';
780     wcsncpy(&pwstToken[iPos + 2], token->pwstToken + iPos + 1, sizeTotal - (iPos + 1));
781     pwstToken[sizeTotal + 1] = L'\0';
782
783     return pwstToken;
784 }
785 /*--------------------------------------------------------------------------*/
786 void updatel(TokenDef* token)
787 {
788     wchar_t* newToken = addl(token);
789     delete[] token->pwstToken;
790     token->pwstToken = newToken;
791 }