* Bug 14156: mfscanf returned [] when datafile contained a header + init variables... 54/17254/5
Antoine ELIAS [Thu, 24 Sep 2015 13:58:21 +0000 (15:58 +0200)]
Change-Id: I927e7b77d710e6d9cc60cc0a57cebdc7e8a72b91

scilab/CHANGES_6.0.X
scilab/modules/fileio/includes/do_xxscanf.h
scilab/modules/fileio/sci_gateway/cpp/sci_mfscanf.cpp
scilab/modules/fileio/src/c/do_xxscanf.c
scilab/modules/fileio/tests/nonreg_tests/bug_14156.dia.ref [new file with mode: 0644]
scilab/modules/fileio/tests/nonreg_tests/bug_14156.tst [new file with mode: 0644]
scilab/modules/fileio/tests/nonreg_tests/bug_14156.txt [new file with mode: 0644]
scilab/modules/string/sci_gateway/cpp/sci_strtod.cpp

index 89167a9..035c553 100644 (file)
@@ -71,6 +71,8 @@ Scilab Bug Fixes
 
 * Bug #14150 fixed - The Windows SDK was not found on Windows 8.1.
 
+* Bug #14156 fixed - mfscanf returned an empty matrix when datafile contained a header.
+
 
             Changes between version 5.5.2 and 6.0.0-alpha-1 of Scilab
             =========================================================
index 6c5b0db..93d0e2c 100644 (file)
@@ -49,7 +49,7 @@ typedef union
     double d;
     wchar_t * s;
 } entry;
-typedef enum {SF_C, SF_S, SF_LUI, SF_SUI, SF_UI, SF_LI, SF_SI, SF_I, SF_LF, SF_F} sfdir;
+typedef enum {SF_C, SF_S, SF_LUI, SF_SUI, SF_UI, SF_LI, SF_SI, SF_I, SF_LF, SF_F, NONE} sfdir;
 
 FILEIO_IMPEXP int do_xxscanf (const wchar_t *fname, FILE *fp, const wchar_t *format, int *nargs, wchar_t *strv, int *retval, rec_entry *buf, sfdir *type);
 #endif /* __DO_XXSCANF_H__ */
index 379a275..b5963a9 100644 (file)
@@ -48,9 +48,17 @@ types::Function::ReturnValue sci_mfscanf(types::typed_list &in, int _iRetCount,
     int retval      = 0;
     int retval_s    = 0;
     int rowcount    = 0;
-    rec_entry buf[MAXSCAN];
+    rec_entry buf[MAXSCAN] = {0};
     entry *data;
-    sfdir type[MAXSCAN], type_s[MAXSCAN];
+    sfdir type[MAXSCAN] = {NONE};
+    sfdir type_s[MAXSCAN] = {NONE};
+
+    for (int i = 0; i < MAXSCAN; ++i)
+    {
+        memset(&buf[i], 0x00, sizeof(rec_entry));
+        type[i] = NONE;
+        type_s[i] = NONE;
+    }
 
     if (size < 2 || size > 3)
     {
@@ -138,7 +146,19 @@ types::Function::ReturnValue sci_mfscanf(types::typed_list &in, int _iRetCount,
                 mseek(iFile, iCurrentPos, SEEK_SET);
             }
 
-            FREE(buf->c);
+            for (int i = 0; i < MAXSCAN; ++i)
+            {
+                if (type[i] == NONE)
+                {
+                    break;
+                }
+
+                if (type[i] == SF_S || type[i] == SF_C)
+                {
+                    FREE(buf[i].c);
+                    buf[i].c = NULL;
+                }
+            }
             break;
         }
 
@@ -165,7 +185,7 @@ types::Function::ReturnValue sci_mfscanf(types::typed_list &in, int _iRetCount,
                 {
                     ps->set(j, data[i + ncol * j].s);
                 }
-                
+
                 IT.push_back(ps);
                 uiFormatUsed |= (1 << 1);
                 break;
@@ -184,7 +204,7 @@ types::Function::ReturnValue sci_mfscanf(types::typed_list &in, int _iRetCount,
                 {
                     p->set(j, data[i + ncol * j].d);
                 }
-                
+
                 IT.push_back(p);
                 uiFormatUsed |= (1 << 2);
                 break;
@@ -299,7 +319,7 @@ types::Function::ReturnValue sci_mfscanf(types::typed_list &in, int _iRetCount,
                                 {
                                     pType->set(iRows * iCols + k, IT[i]->getAs<types::Double>()->get(k));
                                 }
-  
+
                                 IT[i]->killMe();
                                 ITTemp.pop_back();
                                 ITTemp.push_back(pType);
index 4bf77a8..335c766 100644 (file)
 #include "core_math.h"
 #include "os_string.h"
 /*--------------------------------------------------------------------------*/
-typedef int (*XXSCANF) (FILE *, wchar_t *, ...);
-typedef int (*FLUSH) (FILE *);
+typedef int (*XXSCANF) (FILE* , char* , ...);
+typedef int (*FLUSH) (FILE*);
 
 /*--------------------------------------------------------------------------*/
-static void set_xxscanf(FILE * fp, XXSCANF * xxscanf, wchar_t **target, wchar_t **strv)
+static void set_xxscanf(FILE* fp, XXSCANF* xxscanf, char** target, wchar_t* strv)
 {
     if (fp == (FILE *) 0)
     {
-        *target = *strv;
-        *xxscanf = (XXSCANF) swscanf;
+        *target = wide_string_to_UTF8(strv);
+        *xxscanf = (XXSCANF) sscanf;
     }
     else
     {
-        *target = (wchar_t *)fp;
-        *xxscanf = (XXSCANF) fwscanf;
+        *target = (char*)fp;
+        *xxscanf = (XXSCANF) fscanf;
+    }
+}
+static void delete_target(FILE* fp, char* target)
+{
+    if (target && fp == (FILE *) 0)
+    {
+        FREE(target);
     }
 }
-
 /*--------------------------------------------------------------------------*/
 int do_xxscanf (const wchar_t *fname, FILE *fp, const wchar_t *format, int *nargs, wchar_t *strv, int *retval, rec_entry *buf, sfdir *type)
 {
@@ -62,13 +68,14 @@ int do_xxscanf (const wchar_t *fname, FILE *fp, const wchar_t *format, int *narg
     wchar_t backupcurrrentchar;
     wchar_t directive;
     wchar_t *p1 = NULL;
-    wchar_t *target = NULL;
+    char* target = NULL;
     wchar_t *sval = NULL;
     register wchar_t *currentchar = NULL;
+    char* strFormat = NULL;
 
     XXSCANF xxscanf;
 
-    set_xxscanf(fp, &xxscanf, &target, &strv);
+    set_xxscanf(fp, &xxscanf, &target, strv);
     currentchar = format;
     *retval = 0;
 
@@ -147,6 +154,7 @@ int do_xxscanf (const wchar_t *fname, FILE *fp, const wchar_t *format, int *narg
 
             if (*currentchar1 == L'\0')
             {
+                delete_target(fp, target);
                 Scierror(998, _("%s: An error occurred: %s\n"), fname, _("unclosed [ directive."));
                 return DO_XXPRINTF_RET_BUG;
             }
@@ -161,6 +169,7 @@ int do_xxscanf (const wchar_t *fname, FILE *fp, const wchar_t *format, int *narg
 
                 if (*currentchar1 == L'\0')
                 {
+                    delete_target(fp, target);
                     Scierror(998, _("%s: An error occurred: %s\n"), fname, _("unclosed [ directive."));
                     return DO_XXPRINTF_RET_BUG;
                 }
@@ -178,6 +187,7 @@ int do_xxscanf (const wchar_t *fname, FILE *fp, const wchar_t *format, int *narg
 
             if (num_conversion >= MAXSCAN)
             {
+                delete_target(fp, target);
                 Scierror(998, _("%s: An error occurred: too many (> %d) conversion required.\n"), fname, MAXSCAN);
                 return DO_XXPRINTF_RET_BUG;
             }
@@ -189,12 +199,14 @@ int do_xxscanf (const wchar_t *fname, FILE *fp, const wchar_t *format, int *narg
 
                     if (width_flag == 1 && width_val > MAX_STR - 1)
                     {
+                        delete_target(fp, target);
                         Scierror(998, _("%s: An error occurred: field %d is too long (> %d) for %%[ directive.\n"), fname, width_val, MAX_STR - 1);
                         return DO_XXPRINTF_RET_BUG;
                     }
 
                     if ((buf[num_conversion].c = (wchar_t*)MALLOC(MAX_STR * sizeof(wchar_t))) == NULL)
                     {
+                        delete_target(fp, target);
                         return DO_XXPRINTF_MEM_LACK;
                     }
                     ptrtab[num_conversion] = buf[num_conversion].c;
@@ -204,6 +216,7 @@ int do_xxscanf (const wchar_t *fname, FILE *fp, const wchar_t *format, int *narg
                 case L's':
                     if (l_flag + h_flag)
                     {
+                        delete_target(fp, target);
                         Scierror(998, _("%s: An error occurred: %s\n"), fname, _("Bad conversion."));
                         return DO_XXPRINTF_RET_BUG;
                     }
@@ -211,12 +224,14 @@ int do_xxscanf (const wchar_t *fname, FILE *fp, const wchar_t *format, int *narg
                     str_flag = 1;
                     if (width_flag == 1 && width_val > MAX_STR - 1)
                     {
+                        delete_target(fp, target);
                         Scierror(998, _("%s: An error occurred: field %d is too long (< %d) for %%s directive.\n"), fname, width_val, MAX_STR - 1);
                         return DO_XXPRINTF_RET_BUG;
                     }
 
                     if ((buf[num_conversion].c = (wchar_t*)MALLOC(MAX_STR * sizeof(wchar_t))) == NULL)
                     {
+                        delete_target(fp, target);
                         return DO_XXPRINTF_MEM_LACK;
                     }
 
@@ -228,6 +243,7 @@ int do_xxscanf (const wchar_t *fname, FILE *fp, const wchar_t *format, int *narg
                     str_flag = 1;
                     if (l_flag + h_flag)
                     {
+                        delete_target(fp, target);
                         Scierror(998, _("%s: An error occurred: %s\n"), fname, _("Bad conversion."));
                         return DO_XXPRINTF_RET_BUG;
                     }
@@ -243,12 +259,14 @@ int do_xxscanf (const wchar_t *fname, FILE *fp, const wchar_t *format, int *narg
 
                     if (width_flag == 1 && width_val > MAX_STR - 1)
                     {
+                        delete_target(fp, target);
                         Scierror(998, _("%s: An error occurred: field %d is too long (< %d) for %%c directive.\n"), fname, width_val, MAX_STR - 1);
                         return DO_XXPRINTF_RET_BUG;
                     }
 
                     if ((buf[num_conversion].c = (wchar_t*)MALLOC(MAX_STR * sizeof(wchar_t))) == NULL)
                     {
+                        delete_target(fp, target);
                         return DO_XXPRINTF_MEM_LACK;
                     }
 
@@ -312,6 +330,7 @@ int do_xxscanf (const wchar_t *fname, FILE *fp, const wchar_t *format, int *narg
                 case L'G':
                     if (h_flag)
                     {
+                        delete_target(fp, target);
                         Scierror(998, _("%s: An error occurred: %s\n"), fname, _("Bad conversion."));
                         return DO_XXPRINTF_RET_BUG;
                     }
@@ -328,8 +347,11 @@ int do_xxscanf (const wchar_t *fname, FILE *fp, const wchar_t *format, int *narg
                     break;
 
                 default:
+                {
+                    delete_target(fp, target);
                     Scierror(998, _("%s: An error occurred: %s\n"), fname, _("Bad conversion."));
                     return DO_XXPRINTF_RET_BUG;
+                }
             }
             *currentchar = backupcurrrentchar;
         }
@@ -380,6 +402,7 @@ int do_xxscanf (const wchar_t *fname, FILE *fp, const wchar_t *format, int *narg
 
             if (f2 == slast)
             {
+                delete_target(fp, target);
                 Scierror(998, _("%s: An error occurred: format is too long (> %d).\n"), fname, MAX_STR - 1);
                 return DO_XXPRINTF_RET_BUG;
             }
@@ -389,7 +412,8 @@ int do_xxscanf (const wchar_t *fname, FILE *fp, const wchar_t *format, int *narg
         format = sformat;
     }
 
-    *retval = (*xxscanf) ((VPTR) target, format,
+    strFormat = wide_string_to_UTF8(format);
+    *retval = (*xxscanf) ((VPTR) target, strFormat,
                           ptrtab[0], ptrtab[1], ptrtab[2], ptrtab[3], ptrtab[4], ptrtab[5], ptrtab[6], ptrtab[7], ptrtab[8], ptrtab[9],
                           ptrtab[10], ptrtab[11], ptrtab[12], ptrtab[13], ptrtab[14], ptrtab[15], ptrtab[16], ptrtab[17], ptrtab[18], ptrtab[19],
                           ptrtab[20], ptrtab[21], ptrtab[22], ptrtab[23], ptrtab[24], ptrtab[25], ptrtab[26], ptrtab[27], ptrtab[28], ptrtab[29],
@@ -401,6 +425,8 @@ int do_xxscanf (const wchar_t *fname, FILE *fp, const wchar_t *format, int *narg
                           ptrtab[80], ptrtab[81], ptrtab[82], ptrtab[83], ptrtab[84], ptrtab[85], ptrtab[86], ptrtab[87], ptrtab[88], ptrtab[89],
                           ptrtab[90], ptrtab[91], ptrtab[92], ptrtab[93], ptrtab[94], ptrtab[95], ptrtab[96], ptrtab[97], ptrtab[98],
                           ptrtab[MAXSCAN - 1]);
+    FREE(strFormat);
+    delete_target(fp, target);
 
     *nargs = Min(num_conversion + 1, Max(*retval + n_directive_count, 0));
 
diff --git a/scilab/modules/fileio/tests/nonreg_tests/bug_14156.dia.ref b/scilab/modules/fileio/tests/nonreg_tests/bug_14156.dia.ref
new file mode 100644 (file)
index 0000000..4615ded
--- /dev/null
@@ -0,0 +1,27 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2015 - Scilab Enterprises - Charlotte HECQUET
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- CLI SHELL MODE -->
+//
+// <-- Non-regression test for bug 14156 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/show_bug.cgi?id=14156
+//
+// <-- Short Description -->
+// mfscanf returns an empty matrix when datafile contains a header
+fid = mopen(fullfile(SCI, "modules", "fileio", "tests", "nonreg_tests", "bug_14156.txt"), 'r');
+header=mgetl(fid, 1);
+data_all=mfscanf(-1, fid, "%d/%d/%d %d:%d;%lf;%lf;%lf;%lf");
+ref = [1 1 1981 0 0 16.84 2.05 10.07 0.5; ..
+1 1 1981 1 0 16.9 2.17 10.24 0.5; ..
+1 1 1981 2 0 17.47 2.38 10.53 0.5; ..
+1 1 1981 3 0 15.9 2.58 10.84 0.5; ..
+1 1 1981 4 0 14.8 2.71 11.08 0.5; ..
+1 1 1981 5 0 14.54 2.82 11.28 0.5];
+assert_checkequal(data_all, ref);
+mclose();
diff --git a/scilab/modules/fileio/tests/nonreg_tests/bug_14156.tst b/scilab/modules/fileio/tests/nonreg_tests/bug_14156.tst
new file mode 100644 (file)
index 0000000..b1e0fcf
--- /dev/null
@@ -0,0 +1,28 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2015 - Scilab Enterprises - Charlotte HECQUET
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- CLI SHELL MODE -->
+//
+// <-- Non-regression test for bug 14156 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/show_bug.cgi?id=14156
+//
+// <-- Short Description -->
+// mfscanf returns an empty matrix when datafile contains a header
+
+fid = mopen(fullfile(SCI, "modules", "fileio", "tests", "nonreg_tests", "bug_14156.txt"), 'r');
+header=mgetl(fid, 1);
+data_all=mfscanf(-1, fid, "%d/%d/%d %d:%d;%lf;%lf;%lf;%lf");
+ref = [1 1 1981 0 0 16.84 2.05 10.07 0.5; ..
+1 1 1981 1 0 16.9 2.17 10.24 0.5; ..
+1 1 1981 2 0 17.47 2.38 10.53 0.5; ..
+1 1 1981 3 0 15.9 2.58 10.84 0.5; ..
+1 1 1981 4 0 14.8 2.71 11.08 0.5; ..
+1 1 1981 5 0 14.54 2.82 11.28 0.5];
+assert_checkequal(data_all, ref);
+mclose();
diff --git a/scilab/modules/fileio/tests/nonreg_tests/bug_14156.txt b/scilab/modules/fileio/tests/nonreg_tests/bug_14156.txt
new file mode 100644 (file)
index 0000000..7d6add6
--- /dev/null
@@ -0,0 +1,7 @@
+Date;X1;X2;X3;X4
+01/01/1981 00:00;16.84;2.05;10.07;0.5
+01/01/1981 01:00;16.9;2.17;10.24;0.5
+01/01/1981 02:00;17.47;2.38;10.53;0.5
+01/01/1981 03:00;15.9;2.58;10.84;0.5
+01/01/1981 04:00;14.8;2.71;11.08;0.5
+01/01/1981 05:00;14.54;2.82;11.28;0.5
index 32b21ed..ef4a99d 100644 (file)
@@ -41,7 +41,7 @@ types::Function::ReturnValue sci_strtod(types::typed_list &in, int _iRetCount, t
     unsigned long long ullNan = 0x7ff8000000000000;
     double dblNan = *( double* )&ullNan;
 
-    if (in.size() > 2)
+    if (in.size() < 1 || in.size() > 2)
     {
         Scierror(77, _("%s: Wrong number of input argument(s): %d to %d expected.\n"), "strtod", 1, 2);
         return types::Function::Error;