bug 13972 : use of wildcard '*' in printf expressions was not managed 84/16784/5
Antoine ELIAS [Fri, 3 Jul 2015 14:48:49 +0000 (16:48 +0200)]
Change-Id: Ief3777eb9983969dd5762844f0732655f6ed2f74

scilab/CHANGES_6.0.X
scilab/modules/fileio/sci_gateway/cpp/sci_mfprintf.cpp
scilab/modules/output_stream/includes/scilab_sprintf.hxx
scilab/modules/output_stream/sci_gateway/cpp/sci_mprintf.cpp
scilab/modules/output_stream/sci_gateway/cpp/sci_msprintf.cpp
scilab/modules/output_stream/src/cpp/scilab_sprintf.cpp
scilab/modules/output_stream/tests/nonreg_tests/bug_13972.dia.ref [new file with mode: 0644]
scilab/modules/output_stream/tests/nonreg_tests/bug_13972.tst [new file with mode: 0644]
scilab/modules/output_stream/tests/unit_tests/msprintf.dia.ref
scilab/modules/output_stream/tests/unit_tests/msprintf.tst

index 9029156..2fe8cd7 100644 (file)
@@ -89,3 +89,5 @@ Scilab Bug Fixes
 
 * Bug #13838 fixed - Sparse and complex substraction made Scilab crash.
 
+* Bug #13972 fixed - Wildcard ('*') was not managed in printf expressions.
+
index c1ccc92..33f417f 100644 (file)
@@ -51,7 +51,6 @@ Function::ReturnValue sci_mfprintf(types::typed_list &in, int _iRetCount, types:
     int ifileMode                   = 0;
     wchar_t* wcsInput               = NULL;
     wchar_t** wcsStringToWrite      = NULL;
-    ArgumentPosition* pArgs         = NULL;
 
     if (in.size() < 2)
     {
@@ -145,68 +144,9 @@ Function::ReturnValue sci_mfprintf(types::typed_list &in, int _iRetCount, types:
     }
 
     // Checking input string to write in file
-    wcsInput = pFileStr->get(0);
-
-    for (int i = 0; i < (int)wcslen(wcsInput); i++)
-    {
-        if (wcsInput[i] == '%')
-        {
-            iNumberPercent++;
-            if (wcsInput[i + 1] == '%')
-            {
-                iNumberPercent--;
-                i++;
-            }
-        }
-    }
-
-    //Input values must be less or equal than excepted
-    if ((in.size() - 2) > iNumberPercent)
-    {
-        Scierror(999, _("%s: Wrong number of input arguments: at most %d expected.\n"), "mprintf", iNumberPercent);
-        return types::Function::Error;
-    }
-
-    //determine if imput values are ... multiple values
-
-    if ( in.size() > 2 )
-    {
-        int iRefRows = in[2]->getAs<GenericType>()->getRows();
-        for (unsigned int i = 2 ; i < in.size() ; i++)
-        {
-            //all arguments must have the same numbers of rows !
-            if (iRefRows != in[i]->getAs<GenericType>()->getRows())
-            {
-                Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), "mprintf");
-                return types::Function::Error;
-            }
-
-            iNumberCols += in[i]->getAs<GenericType>()->getCols();
-        }
-    }
-
-    if (iNumberCols != iNumberPercent)
-    {
-        Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), "mprintf");
-        return types::Function::Error;
-    }
-
-    //fill ArgumentPosition structure
-    pArgs = new ArgumentPosition[iNumberPercent];
-    int idx = 0;
-    for (unsigned int i = 2 ; i < in.size() ; i++)
-    {
-        for (int j = 0 ; j < in[i]->getAs<GenericType>()->getCols() ; j++)
-        {
-            pArgs[idx].iArg = i;
-            pArgs[idx].iPos = j;
-            pArgs[idx].type = in[i]->getType();
-            idx++;
-        }
-    }
-
     int iNewLine = 0;
-    wcsStringToWrite = scilab_sprintf("mfprintf", wcsInput, in, pArgs, iNumberPercent, &nbrOfLines, &iNewLine);
+    wcsInput = pFileStr->get(0);
+    wcsStringToWrite = scilab_sprintf("mfprintf", wcsInput, in, &nbrOfLines, &iNewLine);
 
     if (isSTD)
     {
@@ -239,8 +179,6 @@ Function::ReturnValue sci_mfprintf(types::typed_list &in, int _iRetCount, types:
     }
 
     FREE(wcsStringToWrite);
-    delete[] pArgs;
-
     return types::Function::OK;
 }
 /*--------------------------------------------------------------------------*/
index a27532e..4fb53f1 100644 (file)
 #include "dynlib_output_stream_gw.h"
 #include "internal.hxx"
 
-typedef struct
+struct TokenDef
 {
     wchar_t* pwstToken;
     types::InternalType::ScilabType outputType;
-    bool bLengthFlag;
+    bool length;
     int width;
+    bool widthStar;
     int prec;
+    bool precStar;
     int typePos;
-} TokenDef;
+    int pos;
+    int col;
+
+    TokenDef() :
+        pwstToken(nullptr),
+        outputType(types::InternalType::ScilabNull),
+        length(false),
+        width(0),
+        widthStar(false),
+        prec(0),
+        precStar(false),
+        typePos(0),
+        pos(0),
+        col(0)
+    {}
+};
+
+OUTPUT_STREAM_IMPEXP_GW wchar_t** scilab_sprintf(const std::string& funcname, const wchar_t* _pwstInput, types::typed_list &in, int* _piOutputRows, int* _piNewLine);
 
 
-typedef struct
-{
-    int iArg;
-    int iPos;
-    types::InternalType::ScilabType type;
-} ArgumentPosition;
-
-OUTPUT_STREAM_IMPEXP_GW wchar_t** scilab_sprintf(const char* _pstName, const wchar_t* _pwstInput, types::typed_list &in, ArgumentPosition* _pArgs, int _iArgsCount, int* _piOutputRows, int* piNewLine);
-
 
 #endif /* !__SCILAB_SPRINTF_HXX__ */
index de3e96f..413d88b 100644 (file)
 #include "string.hxx"
 #include "overload.hxx"
 #include "execvisitor.hxx"
+#include <iterator>
 
 extern "C"
 {
 #include <stdio.h>
 #include "Scierror.h"
 #include "localization.h"
+#include "os_wtoi.h"
 }
 
+int new_sprintf(const std::string& funcname, const wchar_t* _pwstInput, typed_list &in, int* _piOutputRows, int* _piNewLine, wchar_t*** output);
+
 /*--------------------------------------------------------------------------*/
 types::Callable::ReturnValue sci_mprintf(types::typed_list &in, int _iRetCount, types::typed_list &out)
 {
-    //Structure to store, link between % and input value
-    ArgumentPosition* pArgs = NULL;
-
     if (in.size() < 1)
     {
         Scierror(999, _("%s: Wrong number of input arguments: at least %d expected.\n"), "mprintf", 1);
@@ -55,69 +56,14 @@ types::Callable::ReturnValue sci_mprintf(types::typed_list &in, int _iRetCount,
         }
     }
 
-    wchar_t* pwstInput = in[0]->getAs<types::String>()->get()[0];
-    int iNumberPercent = 0;
-    int iNumberPercentPercent = 0;
-    for (int i = 0 ; i < wcslen(pwstInput) ; i++)
-    {
-        if (pwstInput[i] == L'%')
-        {
-            iNumberPercent++;
-            if (pwstInput[i + 1] == L'%')
-            {
-                //it is a %%, not a %_
-                iNumberPercentPercent++;
-                //force incremantation to bypass the second % of %%
-                i++;
-            }
-        }
-    }
-
-    //Input values must be less or equal than excepted
-    if ((in.size() - 1) > iNumberPercent - iNumberPercentPercent)
-    {
-        Scierror(999, _("%s: Wrong number of input arguments: at most %d expected.\n"), "mprintf", iNumberPercent);
-        return types::Function::Error;
-    }
-
-    //determine if imput values are ... multiple values
-    int iNumberCols = 0;
-    if ( in.size() > 1 )
-    {
-        int iRefRows = in[1]->getAs<GenericType>()->getRows();
-        for (int i = 1 ; i < in.size() ; i++)
-        {
-            iNumberCols += in[i]->getAs<GenericType>()->getCols();
-        }
-    }
-
-    if (iNumberCols != iNumberPercent - iNumberPercentPercent)
-    {
-        Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), "mprintf");
-        return types::Function::Error;
-    }
-
-    //fill ArgumentPosition structure
-    pArgs = new ArgumentPosition[iNumberPercent - iNumberPercentPercent];
-    int idx = 0;
-    for (int i = 1 ; i < in.size() ; i++)
-    {
-        for (int j = 0 ; j < in[i]->getAs<GenericType>()->getCols() ; j++)
-        {
-            pArgs[idx].iArg = i;
-            pArgs[idx].iPos = j;
-            pArgs[idx].type = in[i]->getType();
-            idx++;
-        }
-    }
-
     int iOutputRows = 0;
     int iNewLine = 0;
-    wchar_t** pwstOutput = scilab_sprintf("mprintf", pwstInput, in, pArgs, iNumberPercent, &iOutputRows, &iNewLine);
+    wchar_t* pwstInput = in[0]->getAs<types::String>()->get()[0];
+    wchar_t** pwstOutput = scilab_sprintf("mprintf", pwstInput, in, &iOutputRows, &iNewLine);
 
     if (pwstOutput == NULL)
     {
-        delete[] pArgs;
+        //error already set by scilab_sprintf
         return types::Function::Error;
     }
 
@@ -140,7 +86,6 @@ types::Callable::ReturnValue sci_mprintf(types::typed_list &in, int _iRetCount,
     }
 
     FREE(pwstOutput);
-    delete[] pArgs;
     return types::Function::OK;
 }
-/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
\ No newline at end of file
index 1a2b865..9a0a402 100644 (file)
@@ -29,9 +29,6 @@ extern "C"
 /*--------------------------------------------------------------------------*/
 types::Callable::ReturnValue sci_msprintf(types::typed_list &in, int _iRetCount, types::typed_list &out)
 {
-    //Structure to store, link between % and input value
-    ArgumentPosition* pArgs = NULL;
-
     if (in.size() < 1)
     {
         Scierror(999, _("%s: Wrong number of input arguments: at least %d expected.\n"), "msprintf", 1);
@@ -54,75 +51,11 @@ types::Callable::ReturnValue sci_msprintf(types::typed_list &in, int _iRetCount,
         }
     }
 
-    wchar_t* pwstInput = in[0]->getAs<types::String>()->get()[0];
-    int iNumberPercent = 0;
-    int iNumberPercentPercent = 0;
-    for (int i = 0; i < wcslen(pwstInput); i++)
-    {
-        if (pwstInput[i] == L'%')
-        {
-            iNumberPercent++;
-            if (pwstInput[i + 1] == L'%')
-            {
-                //it is a %%, not a %_
-                iNumberPercentPercent++;
-                //force incremantation to bypass the second % of %%
-                i++;
-            }
-        }
-    }
-
-    //Input values must be less or equal than excepted
-    if ((in.size() - 1) > iNumberPercent - iNumberPercentPercent)
-    {
-        Scierror(999, _("%s: Wrong number of input arguments: at most %d expected.\n"), "msprintf", iNumberPercent);
-        return types::Function::Error;
-    }
-
-    //determine if imput values are ... multiple values
-    int iNumberCols = 0;
-    if ( in.size() > 1 )
-    {
-        int iRefRows = in[1]->getAs<GenericType>()->getRows();
-        for (int i = 1 ; i < in.size() ; i++)
-        {
-            //all arguments must have the same numbers of rows !
-            if (iRefRows != in[i]->getAs<GenericType>()->getRows())
-            {
-                Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), "msprintf");
-                return types::Function::Error;
-            }
-
-            iNumberCols += in[i]->getAs<GenericType>()->getCols();
-        }
-    }
-
-    if (iNumberCols != iNumberPercent - iNumberPercentPercent)
-    {
-        Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), "msprintf");
-        return types::Function::Error;
-    }
-
-
-    //fill ArgumentPosition structure
-    pArgs = new ArgumentPosition[iNumberPercent - iNumberPercentPercent];
-    int idx = 0;
-    for (int i = 1 ; i < in.size() ; i++)
-    {
-        for (int j = 0 ; j < in[i]->getAs<GenericType>()->getCols() ; j++)
-        {
-            pArgs[idx].iArg = i;
-            pArgs[idx].iPos = j;
-            pArgs[idx].type = in[i]->getType();
-            idx++;
-        }
-    }
-
     int iOutputRows = 0;
     int iNewLine = 0;
-    wchar_t** pwstOutput = scilab_sprintf("msprintf", pwstInput, in, pArgs, iNumberPercent, &iOutputRows, &iNewLine);
+    wchar_t* pwstInput = in[0]->getAs<types::String>()->get()[0];
+    wchar_t** pwstOutput = scilab_sprintf("msprintf", pwstInput, in, &iOutputRows, &iNewLine);
 
-    delete[] pArgs;
     if (pwstOutput == NULL)
     {
         return types::Function::Error;
index 9c85ee3..8369e38 100644 (file)
@@ -1,8 +1,8 @@
 /*
  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
- *  Copyright (C) 2010 - DIGITEO - Antoine ELIAS
  *  Copyright (C) 2013 - Scilab Enterprises - Calixte DENIZET
  *  Copyright (C) 2013 - Scilab Enterprises - Cedric Delamarre
+ *  Copyright (C) 2015 - Scilab Enterprises - Antoine ELIAS
  *
  *  This file must be used under the terms of the CeCILL.
  *  This source file is licensed as described in the file COPYING, which
@@ -14,6 +14,7 @@
 
 #include <stdio.h>
 #include <cmath>
+#include <list>
 #include "types.hxx"
 #include "double.hxx"
 #include "string.hxx"
@@ -32,281 +33,409 @@ extern "C"
 #include "os_string.h"
 }
 
+static wchar_t* replaceAndCountLines(const wchar_t* _pwstInput, int* _piLines, int* _piNewLine);
+static wchar_t* addl(TokenDef* token);
+static void updatel(TokenDef* token);
+
 #define NanString L"Nan"
 #define InfString L"Inf"
 #define NegInfString L"-Inf"
 
-static wchar_t* replaceAndCountLines(const wchar_t* _pwstInput, int* _piLines, int* _piNewLine);
-static wchar_t* addl(TokenDef* token);
-static void updatel(TokenDef* token);
-wchar_t** scilab_sprintf(const char* _pstName, const wchar_t* _pwstInput, typed_list &in, ArgumentPosition* _pArgs, int _iArgsCount, int* _piOutputRows, int* _piNewLine)
+wchar_t** scilab_sprintf(const std::string& funcname, const wchar_t* _pwstInput, typed_list &in, int* _piOutputRows, int* _piNewLine)
 {
     /* Force Windows display to have two-digit exponent. */
 #ifdef _MSC_VER
     _set_output_format(_TWO_DIGIT_EXPONENT);
 #endif
-    wchar_t** pwstOutput = NULL;
-    wchar_t* pwstFirstOutput = NULL;
+    wchar_t** pwstOutput = nullptr;
+    int rhs = in.size();
+    wchar_t* pwstFirstOutput = nullptr;
     *_piNewLine = 0;
-    size_t pos = 0;
+    int col = 0;
+
+    int first = 1;
+    if (funcname == "mfprintf")
+    {
+        first = 2;
+    }
+
+    size_t posIn = first;
+
+    //compute couple (index in input and col number ).
+    std::list<std::pair<int, int> > inPos;
+    for (int i = first; i < in.size(); ++i)
+    {
+        GenericType* gt = in[i]->getAs<GenericType>();
+        int col = gt->getCols();
+        for (int j = 0; j < col; ++j)
+        {
+            inPos.emplace_back(i, j);
+        }
+    }
+
+    std::list<std::pair<int, int> >::iterator itPos = inPos.begin();
 
     //\n \n\r \r \t to string
     //find number of lines
     // replace \\n \\t... by \n \t...
     pwstFirstOutput = replaceAndCountLines(_pwstInput, _piOutputRows, _piNewLine);
 
-    //no arg, just return _pwstInput value
-    if (_iArgsCount)
-    {
-        //store all sub parts of the input string
-        //for the input string "bla1 %s bla2 %d bla3"
-        //store  :
-        //pwstToken[0] : "bla1 "
-        //pwstToken[1] : "%s bla2 "
-        //pwstToken[2] : "%d bla3"
+    std::list<TokenDef*> token;
 
-        size_t iStart = 0;
-        size_t iEnd = 0;
-        int iToken = 0;
-        int iPosArg = 0;
+    size_t start = 0;
+    size_t end = 0;
+    bool finish = false;
 
-        TokenDef* pToken = new TokenDef[_iArgsCount + 1];
-        wchar_t* pwstStart = pwstFirstOutput;
+    wchar_t* pwstStart = pwstFirstOutput;
+    bool percentpercent = false;
 
-        bool bFinish = false;
-        bool bPercentPercent = false;
-
-        while (!bFinish)
+    while (finish == false)
+    {
+        wchar_t* pwstEnd = wcsstr(pwstStart + (token.size() == 0 ? 0 : 1), L"%");
+        start = pwstStart - pwstFirstOutput;
+        percentpercent = false;
+        if (pwstEnd != nullptr)
         {
-            wchar_t* pwstEnd = wcsstr(pwstStart + (iToken == 0 ? 0 : 1), L"%");
-            iStart = pwstStart - pwstFirstOutput;
-            bPercentPercent = false;
-            if (pwstEnd != NULL)
+            if (token.size() && pwstStart[1] == L'%')
             {
-                if (iToken && pwstStart[1] == L'%')
+                //manage "%%"
+                pwstEnd = wcsstr(pwstEnd + 1, L"%");
+                if (pwstEnd == nullptr)
                 {
-                    //manage "%%"
-                    pwstEnd = wcsstr(pwstEnd + 1, L"%");
-                    if (pwstEnd == NULL)
-                    {
-                        //end of string
-                        iEnd = wcslen(pwstFirstOutput);
-                        bFinish = true;
-                    }
-                    else
-                    {
-                        iEnd = pwstEnd - pwstFirstOutput;
-                    }
-
-                    // skip the first %
-                    iStart++;
-                    bPercentPercent = true;
+                    //end of string
+                    end = wcslen(pwstFirstOutput);
+                    finish = true;
                 }
                 else
                 {
-                    iEnd = pwstEnd - pwstFirstOutput;
+                    end = pwstEnd - pwstFirstOutput;
                 }
+
+                // skip the first %
+                start++;
+                percentpercent = true;
             }
             else
             {
-                //end of string
-                iEnd = wcslen(pwstFirstOutput);
-                bFinish = true;
+                end = pwstEnd - pwstFirstOutput;
             }
+        }
+        else
+        {
+            //end of string
+            end = wcslen(pwstFirstOutput);
+            finish = true;
+        }
 
-            pToken[iToken].pwstToken = new wchar_t[iEnd - iStart + 1];
-            wcsncpy(pToken[iToken].pwstToken, pwstFirstOutput + iStart, iEnd - iStart);
-            pToken[iToken].pwstToken[iEnd - iStart] = L'\0';
-            pToken[iToken].outputType = InternalType::ScilabNull;
+        TokenDef* tok = new TokenDef;
+        tok->pwstToken = new wchar_t[end - start + 1];
+        wcsncpy(tok->pwstToken, pwstFirstOutput + start, end - start);
+        tok->pwstToken[end - start] = L'\0';
+        token.push_back(tok);
 
-            //identify destination type
-            //format : %[flags][width][.precision][length]specifier
-            //pToken[iToken].pwstToken
+        wchar_t* pwstPercent = wcsstr(tok->pwstToken, L"%");
+        if (pwstPercent != nullptr && percentpercent == false)
+        {
+            //looking for flags
+            if (*(pwstPercent + 1) == L'-' ||
+                    *(pwstPercent + 1) == L'+' ||
+                    *(pwstPercent + 1) == L' ' ||
+                    *(pwstPercent + 1) == L'#' ||
+                    *(pwstPercent + 1) == L'0')
+            {
+                pwstPercent++;
+            }
 
-            //find %
-            wchar_t* pwstPercent = wcsstr(pToken[iToken].pwstToken, L"%");
-            if (pwstPercent != NULL && bPercentPercent == false)
+            //looking for width
+            if (*(pwstPercent + 1) == L'*')
             {
-                //looking for flags
-                if (*(pwstPercent + 1) == L'-' ||
-                        *(pwstPercent + 1) == L'+' ||
-                        *(pwstPercent + 1) == L' ' ||
-                        *(pwstPercent + 1) == L'#' ||
-                        *(pwstPercent + 1) == L'0')
+                if (itPos == inPos.end())
                 {
-                    pwstPercent++;
+                    Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
+                    *_piOutputRows = 0;
+                    return nullptr;
                 }
 
-                //looking for width
-                pToken[iToken].width = -1;
-                if (*(pwstPercent + 1) == L'*')
+                int p = (*itPos).first;
+                //input data use to set width
+                if (in[p]->getId() != InternalType::IdScalarDouble)
                 {
-                    pwstPercent++;
+                    Scierror(999, _("%s: Wrong type of input arguments #%d: A real scalar expected.\n"), funcname.data(), p);
+                    *_piOutputRows = 0;
+                    return nullptr;
                 }
-                else
+
+
+                Double* dbl = in[p]->getAs<Double>();
+                tok->width = static_cast<int>(dbl->get()[0]);
+                tok->widthStar = true;
+                ++itPos;
+                ++pwstPercent;
+            }
+            else
+            {
+                //number
+                if (iswdigit(*(pwstPercent + 1)))
                 {
-                    //number
-                    if (iswdigit(*(pwstPercent + 1)))
+                    tok->width = os_wtoi(pwstPercent + 1);
+                    while (iswdigit(*(pwstPercent + 1)))
                     {
-                        pToken[iToken].width = os_wtoi(pwstPercent + 1);
-                        while (iswdigit(*(pwstPercent + 1)))
-                        {
-                            pwstPercent++;
-                        }
+                        pwstPercent++;
                     }
                 }
+            }
 
-                //looking for precision
-                pToken[iToken].prec = -1;
-                if (*(pwstPercent + 1) == L'.')
-                {
-                    pwstPercent++;
+            //looking for precision
+            if (*(pwstPercent + 1) == L'.')
+            {
+                pwstPercent++;
 
-                    if (iswdigit(*(pwstPercent + 1)))
+                if (iswdigit(*(pwstPercent + 1)))
+                {
+                    tok->prec = os_wtoi(pwstPercent + 1);
+                    while (iswdigit(*(pwstPercent + 1)))
                     {
-                        pToken[iToken].prec = os_wtoi(pwstPercent + 1);
-                        while (iswdigit(*(pwstPercent + 1)))
-                        {
-                            pwstPercent++;
-                        }
+                        pwstPercent++;
                     }
                 }
-
-                //looking for length
-                if (*(pwstPercent + 1) == L'h' ||
-                        *(pwstPercent + 1) == L'l' ||
-                        *(pwstPercent + 1) == L'L')
-                {
-                    pToken[iToken].bLengthFlag = true;
-                    pwstPercent++;
-                }
-                else
+                else if (*(pwstPercent + 1) == L'*')
                 {
-                    pToken[iToken].bLengthFlag = false;
+                    if (itPos == inPos.end())
+                    {
+                        Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
+                        *_piOutputRows = 0;
+                        return nullptr;
+                    }
+
+                    int p = (*itPos).first;
+                    //input data use to set prec
+                    if (in[p]->getId() != InternalType::IdScalarDouble)
+                    {
+                        Scierror(999, _("%s: Wrong type of input arguments #%d: A real scalar expected.\n"), funcname.data(), p + 1);
+                        *_piOutputRows = 0;
+                        return nullptr;
+                    }
+
+                    Double* dbl = in[p]->getAs<Double>();
+                    tok->prec = static_cast<int>(dbl->get()[0]);
+                    tok->precStar = true;
+                    ++itPos;
+                    ++pwstPercent;
                 }
+            }
+
+            //looking for length
+            if (*(pwstPercent + 1) == L'h' ||
+                    *(pwstPercent + 1) == L'l' ||
+                    *(pwstPercent + 1) == L'L')
+            {
+                tok->length = true;
+                pwstPercent++;
+            }
+
+            wchar_t wcType = *(pwstPercent + 1);
+            tok->typePos = (pwstPercent + 1) - tok->pwstToken;
 
-                wchar_t wcType = *(pwstPercent + 1);
-                pToken[iToken].typePos = (pwstPercent + 1) - pToken[iToken].pwstToken;
-                switch (wcType)
+            switch (wcType)
+            {
+                case L'i': //integer
+                case L'd': //integer
                 {
-                    case L'i' : //integer
-                    case L'd' : //integer
-                        if (_pArgs[iPosArg].type != InternalType::ScilabDouble)
-                        {
-                            Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), _pstName);
-                            *_piOutputRows = 0;
-                            return NULL;
-                        }
+                    if (itPos == inPos.end())
+                    {
+                        Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
+                        *_piOutputRows = 0;
+                        return nullptr;
+                    }
 
-                        pToken[iToken].outputType = InternalType::ScilabInt32;
+                    int p = (*itPos).first;
+                    int c = (*itPos).second;
+                    if (in[p]->getType() != InternalType::ScilabDouble)
+                    {
+                        Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
+                        *_piOutputRows = 0;
+                        return nullptr;
+                    }
 
-                        iPosArg++;
-                        break;
+                    tok->outputType = InternalType::ScilabInt32;
+                    tok->pos = p;
+                    tok->col = c;
+                    ++itPos;
+                    break;
+                }
+                case L'o': //octal
+                case L'u': //unsigned
+                case L'x': //hex
+                case L'X': //HEX
+                {
+                    if (itPos == inPos.end())
+                    {
+                        Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
+                        *_piOutputRows = 0;
+                        return nullptr;
+                    }
 
-                    case L'o' : //octal
-                    case L'u' : //unsigned
-                    case L'x' : //hex
-                    case L'X' : //HEX
-                        if (_pArgs[iPosArg].type != InternalType::ScilabDouble)
-                        {
-                            Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), _pstName);
-                            *_piOutputRows = 0;
-                            return NULL;
-                        }
+                    int p = (*itPos).first;
+                    int c = (*itPos).second;
+                    if (in[p]->getType() != InternalType::ScilabDouble)
+                    {
+                        Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
+                        *_piOutputRows = 0;
+                        return nullptr;
+                    }
 
-                        pToken[iToken].outputType = InternalType::ScilabUInt32;
+                    tok->outputType = InternalType::ScilabUInt32;
+                    tok->pos = p;
+                    tok->col = c;
+                    ++itPos;
+                    break;
+                }
+                case L'f': //float
+                case L'e': //exp
+                case L'E': //EXP
+                case L'g': //shorter between float or exp
+                case L'G': //shorter between float or EXP
+                {
+                    if (itPos == inPos.end())
+                    {
+                        Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
+                        *_piOutputRows = 0;
+                        return nullptr;
+                    }
 
-                        iPosArg++;
-                        break;
-                    case L'f' : //float
-                    case L'e' : //exp
-                    case L'E' : //EXP
-                    case L'g' : //shorter between float or exp
-                    case L'G' : //shorter between float or EXP
-                        if (_pArgs[iPosArg].type != InternalType::ScilabDouble)
-                        {
-                            Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), _pstName);
-                            *_piOutputRows = 0;
-                            return NULL;
-                        }
+                    int p = (*itPos).first;
+                    int c = (*itPos).second;
+                    if (in[p]->getType() != InternalType::ScilabDouble)
+                    {
+                        Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
+                        *_piOutputRows = 0;
+                        return nullptr;
+                    }
 
-                        pToken[iToken].outputType = InternalType::ScilabDouble;
-                        iPosArg++;
-                        break;
-                    case L's' :
-                    case L'c' :
-                        if (_pArgs[iPosArg].type != InternalType::ScilabString)
-                        {
-                            Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), _pstName);
-                            *_piOutputRows = 0;
-                            return NULL;
-                        }
+                    tok->outputType = InternalType::ScilabDouble;
+                    tok->pos = p;
+                    tok->col = c;
+                    ++itPos;
+                    break;
+                }
+                case L's':
+                case L'c':
+                {
+                    if (itPos == inPos.end())
+                    {
+                        Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
+                        *_piOutputRows = 0;
+                        return nullptr;
+                    }
 
-                        if (pToken[iToken].bLengthFlag == false)
-                        {
-                            updatel(&(pToken[iToken]));
-                        }
+                    int p = (*itPos).first;
+                    int c = (*itPos).second;
+                    if (in[p]->getType() != InternalType::ScilabString)
+                    {
+                        Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
+                        *_piOutputRows = 0;
+                        return nullptr;
+                    }
+
+                    if (tok->length == false)
+                    {
+                        updatel(tok);
+                    }
 
-                        pToken[iToken].outputType = InternalType::ScilabString;
-                        iPosArg++;
-                        break;
-                    default :
-                        //houston ...
-                        break;
+                    tok->outputType = InternalType::ScilabString;
+                    tok->pos = p;
+                    tok->col = c;
+                    ++itPos;
+                    break;
                 }
+                default:
+                    Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), funcname.data());
+                    *_piOutputRows = 0;
+                    return nullptr;
+                    break;
             }
-
-            pwstStart = pwstEnd;
-            iToken++;
         }
 
-        FREE(pwstFirstOutput);
-        pwstFirstOutput = NULL;
+        //continue
+        pwstStart = pwstEnd;
+    }
 
-        int iLoop = 1;
-        int iFirstArg = 1;
-        if (strcmp(_pstName, "mfprintf") == 0)
-        {
-            iFirstArg = 2;
-        }
+    FREE(pwstFirstOutput);
+    pwstFirstOutput = nullptr;
 
-        if (in.size() > 1)
-        {
-            iLoop = in[iFirstArg]->getAs<GenericType>()->getRows();
-            for (int i = iFirstArg + 1 ; i < in.size() ; i++)
-            {
-                iLoop = std::min(iLoop, in[i]->getAs<GenericType>()->getRows());
-            }
-        }
+    int iLoop = 1;
 
-        if (*_piNewLine || (*_piOutputRows) > 1)
+    if (rhs > first)
+    {
+        std::list<TokenDef*>::iterator it = std::next(token.begin());
+        iLoop = in[(*it)->pos]->getAs<GenericType>()->getRows();
+        for (; it != token.end(); ++it)
         {
-            (*_piOutputRows) *= iLoop;
+            iLoop = std::min(iLoop, in[(*it)->pos]->getAs<GenericType>()->getRows());
         }
+    }
+
+    if (*_piNewLine || (*_piOutputRows) > 1)
+    {
+        (*_piOutputRows) *= iLoop;
+    }
+
+    //if ((token.size() - 1) != inPos.size())
+    //{
+    //    Scierror(999, _("%s: Wrong number of input arguments: at most %d expected.\n"), funcname.data(), token.size() - 1);
+    //    *_piOutputRows = 0;
+    //    return nullptr;
+    //}
+
+    std::wostringstream oFirstOutput;
+    for (int j = 0; j < iLoop; j++)
+    {
+        //copy the 0th token
+        TokenDef* f = token.front();
+        oFirstOutput << f->pwstToken;
 
-        std::wostringstream oFirstOutput;
-        for (int j = 0 ; j < iLoop ; j++)
+        //start at 1, the 0th is always without %
+        std::list<TokenDef*>::iterator it = std::next(token.begin());
+        for (; it != token.end(); ++it)
         {
-            //copy the 0th token
-            oFirstOutput << pToken[0].pwstToken;
-            iPosArg = 0;
-            //start at 1, the 0th is always without %
-            for (int i = 1 ; i < _iArgsCount + 1 ; i++)
+            TokenDef* tok = *it;
+            switch (tok->outputType)
             {
-                if (pToken[i].outputType == InternalType::ScilabDouble)
+                case InternalType::ScilabDouble:
                 {
                     wchar_t pwstTemp[bsiz];
-                    double dblVal = in[_pArgs[iPosArg].iArg]->getAs<Double>()->get(j, _pArgs[iPosArg].iPos);
+                    double dblVal = in[tok->pos]->getAs<Double>()->get(j, tok->col);
 
-                    if (finite(dblVal))
+                    if (std::isfinite(dblVal))
                     {
-                        os_swprintf(pwstTemp, bsiz, pToken[i].pwstToken, dblVal);
+                        if (tok->widthStar)
+                        {
+                            if (tok->precStar)
+                            {
+                                os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->width, tok->prec, dblVal);
+                            }
+                            else
+                            {
+                                os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->width, dblVal);
+                            }
+                        }
+                        else
+                        {
+                            if (tok->precStar)
+                            {
+                                os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->prec, dblVal);
+                            }
+                            else
+                            {
+                                os_swprintf(pwstTemp, bsiz, tok->pwstToken, dblVal);
+                            }
+                        }
                     }
                     else
                     {
-                        wchar_t* newToken = addl(&pToken[i]);
+                        wchar_t* newToken = addl(tok);
 
-                        if (ISNAN(dblVal))
+                        if (std::isnan(dblVal))
                         {
                             os_swprintf(pwstTemp, bsiz, newToken, NanString);
                         }
@@ -321,24 +450,45 @@ wchar_t** scilab_sprintf(const char* _pstName, const wchar_t* _pwstInput, typed_
 
                         delete[] newToken;
                     }
-                    iPosArg++;
+
                     oFirstOutput << pwstTemp;
+                    break;
                 }
-                else if (pToken[i].outputType == InternalType::ScilabInt32)
+                case InternalType::ScilabInt32:
                 {
-
                     wchar_t pwstTemp[bsiz];
-                    double dblVal = in[_pArgs[iPosArg].iArg]->getAs<Double>()->get(j, _pArgs[iPosArg].iPos);
-
-                    if (finite(dblVal))
+                    double dblVal = in[tok->pos]->getAs<Double>()->get(j, tok->col);
+                    int iVal = (int)dblVal;
+                    if (std::isfinite(dblVal))
                     {
-                        os_swprintf(pwstTemp, bsiz, pToken[i].pwstToken, (int)dblVal);
+                        if (tok->widthStar)
+                        {
+                            if (tok->precStar)
+                            {
+                                os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->width, tok->prec, iVal);
+                            }
+                            else
+                            {
+                                os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->width, iVal);
+                            }
+                        }
+                        else
+                        {
+                            if (tok->precStar)
+                            {
+                                os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->prec, iVal);
+                            }
+                            else
+                            {
+                                os_swprintf(pwstTemp, bsiz, tok->pwstToken, iVal);
+                            }
+                        }
                     }
                     else
                     {
-                        wchar_t* newToken = addl(&pToken[i]);
+                        wchar_t* newToken = addl(tok);
 
-                        if (ISNAN(dblVal))
+                        if (std::isnan(dblVal))
                         {
                             os_swprintf(pwstTemp, bsiz, newToken, NanString);
                         }
@@ -356,24 +506,46 @@ wchar_t** scilab_sprintf(const char* _pstName, const wchar_t* _pwstInput, typed_
 
                         delete[] newToken;
                     }
-                    iPosArg++;
+
                     oFirstOutput << pwstTemp;
+                    break;
                 }
-                else if (pToken[i].outputType == InternalType::ScilabUInt32)
+                case InternalType::ScilabUInt32:
                 {
-
                     wchar_t pwstTemp[bsiz];
-                    double dblVal = in[_pArgs[iPosArg].iArg]->getAs<Double>()->get(j, _pArgs[iPosArg].iPos);
+                    double dblVal = in[tok->pos]->getAs<Double>()->get(j, tok->col);
+                    unsigned int iVal = (unsigned int)dblVal;
 
-                    if (finite(dblVal))
+                    if (std::isfinite(dblVal))
                     {
-                        os_swprintf(pwstTemp, bsiz, pToken[i].pwstToken, (unsigned int)dblVal);
+                        if (tok->widthStar)
+                        {
+                            if (tok->precStar)
+                            {
+                                os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->width, tok->prec, iVal);
+                            }
+                            else
+                            {
+                                os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->width, iVal);
+                            }
+                        }
+                        else
+                        {
+                            if (tok->precStar)
+                            {
+                                os_swprintf(pwstTemp, bsiz, tok->pwstToken, tok->prec, iVal);
+                            }
+                            else
+                            {
+                                os_swprintf(pwstTemp, bsiz, tok->pwstToken, iVal);
+                            }
+                        }
                     }
                     else
                     {
-                        wchar_t* newToken = addl(&pToken[i]);
+                        wchar_t* newToken = addl(tok);
 
-                        if (ISNAN(dblVal))
+                        if (std::isnan(dblVal))
                         {
                             os_swprintf(pwstTemp, bsiz, newToken, NanString);
                         }
@@ -391,20 +563,22 @@ wchar_t** scilab_sprintf(const char* _pstName, const wchar_t* _pwstInput, typed_
 
                         delete[] newToken;
                     }
-                    iPosArg++;
+
                     oFirstOutput << pwstTemp;
+                    break;
                 }
-                else if (pToken[i].outputType == InternalType::ScilabString)
+                case InternalType::ScilabString:
                 {
-                    wchar_t* pwstStr = NULL;
+                    wchar_t* pwstStr = nullptr;
 
-                    if (in[iPosArg + 1]->isDouble() && ISNAN(in[iPosArg + 1]->getAs<types::Double>()->get(0)))
+                    InternalType* it = in[tok->pos];
+                    if (it->isDouble() && std::isnan(it->getAs<types::Double>()->get(0)))
                     {
                         pwstStr = NanString;
                     }
-                    else if (in[iPosArg + 1]->isDouble() && finite(in[iPosArg + 1]->getAs<types::Double>()->get(0)) == false)
+                    else if (it->isDouble() && std::isfinite(it->getAs<types::Double>()->get(0)) == false)
                     {
-                        if (std::signbit(in[iPosArg + 1]->getAs<types::Double>()->get(0)))
+                        if (std::signbit(it->getAs<types::Double>()->get(0)))
                         {
                             pwstStr = NegInfString;
                         }
@@ -415,71 +589,83 @@ wchar_t** scilab_sprintf(const char* _pstName, const wchar_t* _pwstInput, typed_
                     }
                     else
                     {
-                        pwstStr = in[_pArgs[iPosArg].iArg]->getAs<types::String>()->get(j, _pArgs[iPosArg].iPos);
+                        pwstStr = it->getAs<types::String>()->get(j, tok->col);
                     }
 
-                    int posC = (int)wcscspn(pToken[i].pwstToken, L"c");
-                    int posS = (int)wcscspn(pToken[i].pwstToken, L"s");
+                    int posC = (int)wcscspn(tok->pwstToken, L"c");
+                    int posS = (int)wcscspn(tok->pwstToken, L"s");
 
                     if (posS == 0 || posC == 0)
                     {
                         *_piOutputRows = 0;
-                        return NULL;
+                        return nullptr;
                     }
 
                     bool bC = posC < posS;
                     int len = 1;
-                    if (pToken[i].prec == -1)
+                    if (tok->prec)
                     {
                         if (bC == false)
                         {
-                            len = (int)wcslen(pwstStr);
+                            len = std::min(std::abs(tok->prec), (int)wcslen(pwstStr));
                         }
                     }
                     else
                     {
                         if (bC == false)
                         {
-                            len = std::min(pToken[i].prec, (int)wcslen(pwstStr));
+                            len = (int)wcslen(pwstStr);
                         }
                     }
 
-                    int tokenLen = (int)wcslen(pToken[i].pwstToken);
+                    int tokenLen = (int)wcslen(tok->pwstToken);
                     len += tokenLen;
-                    len = std::max(len, pToken[i].width);
+                    len = std::max(len, std::abs(tok->width));
                     //add len of string after token like "%20s>>>" add space for ">>>"
                     len += (tokenLen - (bC ? posC : posS));
                     wchar_t* pwstTemp = (wchar_t*)MALLOC((len + 1) * sizeof(wchar_t));
 
                     if (bC)
                     {
-                        os_swprintf(pwstTemp, len + 1, pToken[i].pwstToken, pwstStr[0]);
+                        if (tok->widthStar)
+                        {
+                            os_swprintf(pwstTemp, len + 1, tok->pwstToken, tok->width, pwstStr[0]);
+                        }
+                        else
+                        {
+                            os_swprintf(pwstTemp, len + 1, tok->pwstToken, pwstStr[0]);
+                        }
                     }
                     else
                     {
-                        os_swprintf(pwstTemp, len + 1, pToken[i].pwstToken, pwstStr);
+                        if (tok->widthStar)
+                        {
+                            os_swprintf(pwstTemp, len + 1, tok->pwstToken, tok->width, pwstStr);
+                        }
+                        else
+                        {
+                            os_swprintf(pwstTemp, len + 1, tok->pwstToken, pwstStr);
+                        }
                     }
 
                     oFirstOutput << pwstTemp;
                     FREE(pwstTemp);
-                    iPosArg++;
+                    break;
                 }
-                else
-                {
+                default:
                     // management of %%
-                    oFirstOutput << pToken[i].pwstToken;
-                }
+                    oFirstOutput << tok->pwstToken;
+                    break;
             }
         }
+    }
 
-        pwstFirstOutput = os_wcsdup((wchar_t*)oFirstOutput.str().c_str());
-
-        for (int j = 0; j < _iArgsCount + 1; ++j)
-        {
-            delete[] pToken[j].pwstToken;
-        }
-        delete[] pToken;
+    pwstFirstOutput = os_wcsdup((wchar_t*)oFirstOutput.str().c_str());
 
+    for (auto& tok : token)
+    {
+        delete[] tok->pwstToken;
+        delete tok;
     }
 
     pwstOutput = (wchar_t**)MALLOC((*_piOutputRows) * sizeof(wchar_t*));
@@ -487,7 +673,7 @@ wchar_t** scilab_sprintf(const char* _pstName, const wchar_t* _pwstInput, typed_
     size_t iLen = wcslen(pwstFirstOutput);
     int iStart = 0;
     int j = 0;
-    for (int i = 0 ; i < iLen ; i++)
+    for (int i = 0; i < iLen; i++)
     {
         if (pwstFirstOutput[i] == L'\n')
         {
@@ -509,6 +695,7 @@ wchar_t** scilab_sprintf(const char* _pstName, const wchar_t* _pwstInput, typed_
     return pwstOutput;
 }
 /*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
 // replace "\\n" "\\r" "\\t" "\\r\\n" by '\n' '\r' '\t' '\n'
 // count number of lines
 // indicate if one '\n' is at the end of string
@@ -520,7 +707,7 @@ static wchar_t* replaceAndCountLines(const wchar_t* _pwstInput, int* _piLines, i
     int iPos = 0;
     *_piLines = 1;
 
-    for (int i = 0 ; i < iInputLen ; i++)
+    for (int i = 0; i < iInputLen; i++)
     {
         if (_pwstInput[i] == L'\\')
         {
@@ -531,12 +718,12 @@ static wchar_t* replaceAndCountLines(const wchar_t* _pwstInput, int* _piLines, i
 
             switch (_pwstInput[i + 1])
             {
-                case L'n' :
+                case L'n':
                     pwstFirstOutput[iPos++] = L'\n';
                     (*_piLines)++;
                     i++;
                     break;
-                case L'r' :
+                case L'r':
                     if (iInputLen > i + 3 && _pwstInput[i + 2] == L'\\' && _pwstInput[i + 3] == L'n')
                     {
                         pwstFirstOutput[iPos++] = L'\n';
@@ -549,7 +736,7 @@ static wchar_t* replaceAndCountLines(const wchar_t* _pwstInput, int* _piLines, i
                         i++;
                     }
                     break;
-                case L't' :
+                case L't':
                     pwstFirstOutput[iPos++] = L'\t';
                     i++;
                     break;
@@ -590,7 +777,7 @@ wchar_t* addl(TokenDef* token)
     pwstToken[iPos] = L'l';
     pwstToken[iPos + 1] = L's';
     wcsncpy(&pwstToken[iPos + 2], token->pwstToken + iPos + 1, sizeTotal - (iPos + 1));
-    pwstToken[sizeTotal + 1]  = L'\0';
+    pwstToken[sizeTotal + 1] = L'\0';
 
     return pwstToken;
 }
diff --git a/scilab/modules/output_stream/tests/nonreg_tests/bug_13972.dia.ref b/scilab/modules/output_stream/tests/nonreg_tests/bug_13972.dia.ref
new file mode 100644 (file)
index 0000000..c6bc34f
--- /dev/null
@@ -0,0 +1,119 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2015 - Scilab Enterprises - Antoine ELIAS
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- CLI SHELL MODE -->
+//
+// <-- Non-regression test for bug 13972 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/show_bug.cgi?id=13972
+//
+// <-- Short Description -->
+// use of wildcard '*' in printf expressions was not managed
+//
+//with double
+printf("|%*f|\n", 20, rand());
+|            0.211325|
+printf("|%*f|\n", -20, rand());
+|0.756044            |
+printf("|%.*f|\n", 8, rand());
+|0.00022113|
+printf("|%.*f|\n", -8, rand());
+|0.330327|
+printf("|%*.*f|\n", 20, 8, rand());
+|          0.66538110|
+printf("|%*.*f|\n", 20, -8, rand());
+|            0.628392|
+printf("|%*.*f|\n", -20, 8, rand());
+|0.84974524          |
+printf("|%*.*f|\n", -20, -8, rand());
+|0.685731            |
+//with string
+printf("|%s|\n", "test");
+|test|
+printf("|%*s|\n", -10, "test");
+|test      |
+printf("|%*s|\n", -5, "test");
+|test |
+printf("|%*s|\n", 0, "test");
+|test|
+printf("|%*s|\n", 5, "test");
+| test|
+printf("|%*s|\n", 10, "test");
+|      test|
+//multiple
+printf("|%*s|%*s|%*s|%*s|\n", -10, "test", -5, "test", 5, "test", 10, "test");
+|test      |test | test|      test|
+printf("|%*s|\n", -10, ["t";"tt";"ttt";"tttt";"ttttt";"tttttt";"ttttttt";"tttttttt";"ttttttttt";"tttttttttt"]);
+|t         |
+|tt        |
+|ttt       |
+|tttt      |
+|ttttt     |
+|tttttt    |
+|ttttttt   |
+|tttttttt  |
+|ttttttttt |
+|tttttttttt|
+printf("|%*s|\n", 10, ["t";"tt";"ttt";"tttt";"ttttt";"tttttt";"ttttttt";"tttttttt";"ttttttttt";"tttttttttt"]);
+|         t|
+|        tt|
+|       ttt|
+|      tttt|
+|     ttttt|
+|    tttttt|
+|   ttttttt|
+|  tttttttt|
+| ttttttttt|
+|tttttttttt|
+printf("|%*d|%*d|%*d|%*d|\n", -10, -10, -5, -5, 5, 5, 10, 10);
+|-10       |-5   |    5|        10|
+printf("|%*d|\n", -8, [1;22;333;4444;55555;666666;7777777;88888888]);
+|1       |
+|22      |
+|333     |
+|4444    |
+|55555   |
+|666666  |
+|7777777 |
+|88888888|
+printf("|%*d|\n", 8, [1;22;333;4444;55555;666666;7777777;88888888]);
+|       1|
+|      22|
+|     333|
+|    4444|
+|   55555|
+|  666666|
+| 7777777|
+|88888888|
+printf("|%0*d|\n", 8, [1;22;333;4444;55555;666666;7777777;88888888]);
+|00000001|
+|00000022|
+|00000333|
+|00004444|
+|00055555|
+|00666666|
+|07777777|
+|88888888|
+printf("|%.*d|\n", -8, [1;22;333;4444;55555;666666;7777777;88888888]);
+|1|
+|22|
+|333|
+|4444|
+|55555|
+|666666|
+|7777777|
+|88888888|
+printf("|%.*d|\n", 8, [1;22;333;4444;55555;666666;7777777;88888888]);
+|00000001|
+|00000022|
+|00000333|
+|00004444|
+|00055555|
+|00666666|
+|07777777|
+|88888888|
diff --git a/scilab/modules/output_stream/tests/nonreg_tests/bug_13972.tst b/scilab/modules/output_stream/tests/nonreg_tests/bug_13972.tst
new file mode 100644 (file)
index 0000000..8da7998
--- /dev/null
@@ -0,0 +1,47 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2015 - Scilab Enterprises - Antoine ELIAS
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- CLI SHELL MODE -->
+//
+// <-- Non-regression test for bug 13972 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/show_bug.cgi?id=13972
+//
+// <-- Short Description -->
+// use of wildcard '*' in printf expressions was not managed
+//
+
+//with double
+printf("|%*f|\n", 20, rand());
+printf("|%*f|\n", -20, rand());
+printf("|%.*f|\n", 8, rand());
+printf("|%.*f|\n", -8, rand());
+printf("|%*.*f|\n", 20, 8, rand());
+printf("|%*.*f|\n", 20, -8, rand());
+printf("|%*.*f|\n", -20, 8, rand());
+printf("|%*.*f|\n", -20, -8, rand());
+
+//with string
+printf("|%s|\n", "test");
+printf("|%*s|\n", -10, "test");
+printf("|%*s|\n", -5, "test");
+printf("|%*s|\n", 0, "test");
+printf("|%*s|\n", 5, "test");
+printf("|%*s|\n", 10, "test");
+
+//multiple
+printf("|%*s|%*s|%*s|%*s|\n", -10, "test", -5, "test", 5, "test", 10, "test");
+printf("|%*s|\n", -10, ["t";"tt";"ttt";"tttt";"ttttt";"tttttt";"ttttttt";"tttttttt";"ttttttttt";"tttttttttt"]);
+printf("|%*s|\n", 10, ["t";"tt";"ttt";"tttt";"ttttt";"tttttt";"ttttttt";"tttttttt";"ttttttttt";"tttttttttt"]);
+
+printf("|%*d|%*d|%*d|%*d|\n", -10, -10, -5, -5, 5, 5, 10, 10);
+printf("|%*d|\n", -8, [1;22;333;4444;55555;666666;7777777;88888888]);
+printf("|%*d|\n", 8, [1;22;333;4444;55555;666666;7777777;88888888]);
+printf("|%0*d|\n", 8, [1;22;333;4444;55555;666666;7777777;88888888]);
+printf("|%.*d|\n", -8, [1;22;333;4444;55555;666666;7777777;88888888]);
+printf("|%.*d|\n", 8, [1;22;333;4444;55555;666666;7777777;88888888]);
index 02d512d..72f308a 100644 (file)
@@ -121,9 +121,6 @@ B = 100*rand(nb_row,1);
 assert_checkfalse(execstr("msprintf(""%10s => %08.4f %08.4f %08.4f\n"",A,B,B);","errcatch")     == 0);
 refMsg = msprintf(_("%s: Wrong number of input arguments: data doesn''t fit with format.\n"), "msprintf");
 assert_checkerror("msprintf(""%10s => %08.4f %08.4f %08.4f\n"",A,B,B);", refMsg);
-assert_checkfalse(execstr("msprintf(""%10s => %08.4f %08.4f %08.4f\n"",A,B,B,B,B);","errcatch")     == 0);
-refMsg = msprintf(_("%s: Wrong number of input arguments: at most %d expected.\n"), "msprintf", 4);
-assert_checkerror("msprintf(""%10s => %08.4f %08.4f %08.4f\n"",A,B,B,B,B);", refMsg);
 // No arg
 assert_checkfalse(execstr("msprintf();","errcatch")     == 0);
 refMsg = msprintf(_("%s: Wrong number of input arguments: at least %d expected.\n"), "msprintf", 1);
index e0858fd..15c48b8 100644 (file)
@@ -183,10 +183,6 @@ assert_checkfalse(execstr("msprintf(""%10s => %08.4f %08.4f %08.4f\n"",A,B,B);",
 refMsg = msprintf(_("%s: Wrong number of input arguments: data doesn''t fit with format.\n"), "msprintf");
 assert_checkerror("msprintf(""%10s => %08.4f %08.4f %08.4f\n"",A,B,B);", refMsg);
 
-assert_checkfalse(execstr("msprintf(""%10s => %08.4f %08.4f %08.4f\n"",A,B,B,B,B);","errcatch")     == 0);
-refMsg = msprintf(_("%s: Wrong number of input arguments: at most %d expected.\n"), "msprintf", 4);
-assert_checkerror("msprintf(""%10s => %08.4f %08.4f %08.4f\n"",A,B,B,B,B);", refMsg);
-
 // No arg
 assert_checkfalse(execstr("msprintf();","errcatch")     == 0);
 refMsg = msprintf(_("%s: Wrong number of input arguments: at least %d expected.\n"), "msprintf", 1);