c1ccc924e8ea0c19a69e8105c4e22128bd66a727
[scilab.git] / scilab / modules / fileio / sci_gateway / cpp / sci_mfprintf.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2006 - INRIA - Allan CORNET
4 * Copyright (C) 2009 - DIGITEO - Allan CORNET
5 * Copyright (C) 2010 - DIGITEO - Antoine ELIAS
6 * Copyright (C) 2011 - DIGITEO - Cedric DELAMARRE
7 *
8 * This file must be used under the terms of the CeCILL.
9 * This source file is licensed as described in the file COPYING, which
10 * you should have received as part of this distribution.  The terms
11 * are also available at
12 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
13 *
14 */
15 /*--------------------------------------------------------------------------*/
16 #include "filemanager.hxx"
17 #include "fileio_gw.hxx"
18 #include "function.hxx"
19 #include "double.hxx"
20 #include "string.hxx"
21 #include "scilab_sprintf.hxx"
22 #include "overload.hxx"
23 #include "execvisitor.hxx"
24
25 extern "C"
26 {
27 #include <stdio.h>
28 #include "localization.h"
29 #include "Scierror.h"
30 #include "sci_malloc.h"
31 #include "configvariable_interface.h"
32 #include "mputl.h"
33 }
34 /*--------------------------------------------------------------------------*/
35 #ifdef _MSC_VER
36 static BOOL forceSTDERRredirect = TRUE;
37 #endif
38
39 using namespace types;
40 using namespace ast;
41 /*--------------------------------------------------------------------------*/
42
43 Function::ReturnValue sci_mfprintf(types::typed_list &in, int _iRetCount, types::typed_list &out)
44 {
45     BOOL isSTD                      = FALSE;
46     BOOL isSTDErr                   = FALSE;
47     int iFile                       = -1; //default file : last opened file
48     unsigned int iNumberPercent     = 0;
49     unsigned int iNumberCols        = 0;
50     int nbrOfLines                  = 0;
51     int ifileMode                   = 0;
52     wchar_t* wcsInput               = NULL;
53     wchar_t** wcsStringToWrite      = NULL;
54     ArgumentPosition* pArgs         = NULL;
55
56     if (in.size() < 2)
57     {
58         Scierror(77, _("%s: Wrong number of input argument(s): At least %d expected.\n"), "mfprintf", 2);
59         return types::Function::Error;
60     }
61
62     if (in[0]->isDouble() == false)
63     {
64         Scierror(999, _("%s: Wrong type for input argument #%d: A Real expected.\n"), "mfprintf", 1);
65         return types::Function::Error;
66     }
67
68     types::Double* pFileId = in[0]->getAs<types::Double>();
69     if (pFileId->isScalar() == false || pFileId->isComplex())
70     {
71         Scierror(999, _("%s: Wrong type for input argument #%d: A Real expected.\n"), "mfprintf", 1);
72         return types::Function::Error;
73     }
74
75     if (in[1]->isString() == false)
76     {
77         Scierror(999, _("%s: Wrong type for input argument #%d: A String expected.\n"), "mfprintf", 2);
78         return types::Function::Error;
79     }
80
81     types::String* pFileStr = in[1]->getAs<types::String>();
82     if (pFileStr->isScalar() == false)
83     {
84         Scierror(999, _("%s: Wrong type for input argument #%d: A String expected.\n"), "mfprintf", 2);
85         return types::Function::Error;
86     }
87
88     for (unsigned int i = 2 ; i < in.size() ; i++)
89     {
90         if (in[i]->isDouble() == false && in[i]->isString() == false)
91         {
92             ast::ExecVisitor exec;
93             std::wstring wstFuncName = L"%" + in[i]->getShortTypeStr() + L"_mfprintf";
94             return Overload::call(wstFuncName, in, _iRetCount, out, &exec);
95         }
96     }
97
98     // checking ID of file
99     iFile = static_cast<int>(pFileId->get(0));
100
101     if (FileManager::getFile(iFile) == NULL)
102     {
103         Scierror(999, _("%s: Wrong file descriptor: %d.\n"), "mfprintf", iFile);
104         return types::Function::Error;
105     }
106
107     switch (iFile)
108     {
109         case 0:
110 #ifdef _MSC_VER
111             if ((getScilabMode()  == SCILAB_STD) && (forceSTDERRredirect == TRUE))
112             {
113                 //  Console redirect stderr --> CONOUT$
114                 freopen("CONOUT$", "wb", stderr);
115                 forceSTDERRredirect = FALSE;
116             }
117 #endif
118             isSTDErr = TRUE;
119         case 6:
120             isSTD = TRUE;
121             break;
122         case 5:
123             Scierror(999, _("%s: Wrong file descriptor: %d.\n"), "mfprintf", iFile);
124             return types::Function::Error;
125         default:
126             isSTD = FALSE;
127             types::File* pFile = FileManager::getFile(iFile);
128             // file opened with fortran open function
129             if (pFile->getFileType() == 1)
130             {
131                 Scierror(999, _("%s: Wrong file descriptor: %d.\n"), "mfprintf", iFile);
132                 return types::Function::Error;
133             }
134             ifileMode = pFile->getFileModeAsInt();
135             break;
136     }
137
138     /* checks file mode */
139     /* bug 3898 */
140     /* read only attrib 1xx*/
141     if ((ifileMode >= 100) && (ifileMode < 200) && ((ifileMode % 100) < 10) /* check that it is not r+ */ && !isSTD)
142     {
143         Scierror(999, _("%s: Wrong file mode: READ only.\n"), "mfprintf");
144         return types::Function::Error;
145     }
146
147     // Checking input string to write in file
148     wcsInput = pFileStr->get(0);
149
150     for (int i = 0; i < (int)wcslen(wcsInput); i++)
151     {
152         if (wcsInput[i] == '%')
153         {
154             iNumberPercent++;
155             if (wcsInput[i + 1] == '%')
156             {
157                 iNumberPercent--;
158                 i++;
159             }
160         }
161     }
162
163     //Input values must be less or equal than excepted
164     if ((in.size() - 2) > iNumberPercent)
165     {
166         Scierror(999, _("%s: Wrong number of input arguments: at most %d expected.\n"), "mprintf", iNumberPercent);
167         return types::Function::Error;
168     }
169
170     //determine if imput values are ... multiple values
171
172     if ( in.size() > 2 )
173     {
174         int iRefRows = in[2]->getAs<GenericType>()->getRows();
175         for (unsigned int i = 2 ; i < in.size() ; i++)
176         {
177             //all arguments must have the same numbers of rows !
178             if (iRefRows != in[i]->getAs<GenericType>()->getRows())
179             {
180                 Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), "mprintf");
181                 return types::Function::Error;
182             }
183
184             iNumberCols += in[i]->getAs<GenericType>()->getCols();
185         }
186     }
187
188     if (iNumberCols != iNumberPercent)
189     {
190         Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), "mprintf");
191         return types::Function::Error;
192     }
193
194     //fill ArgumentPosition structure
195     pArgs = new ArgumentPosition[iNumberPercent];
196     int idx = 0;
197     for (unsigned int i = 2 ; i < in.size() ; i++)
198     {
199         for (int j = 0 ; j < in[i]->getAs<GenericType>()->getCols() ; j++)
200         {
201             pArgs[idx].iArg = i;
202             pArgs[idx].iPos = j;
203             pArgs[idx].type = in[i]->getType();
204             idx++;
205         }
206     }
207
208     int iNewLine = 0;
209     wcsStringToWrite = scilab_sprintf("mfprintf", wcsInput, in, pArgs, iNumberPercent, &nbrOfLines, &iNewLine);
210
211     if (isSTD)
212     {
213         for (int i = 0; i < nbrOfLines; i++)
214         {
215             if (isSTDErr)
216             {
217                 std::wcerr << wcsStringToWrite[i];
218             }
219             else
220             {
221                 scilabForcedWriteW(wcsStringToWrite[i]);
222             }
223         }
224         scilabForcedWriteW(L"\n");
225     }
226     else
227     {
228         int iRet = mputl(iFile, wcsStringToWrite, nbrOfLines, (BOOL)iNewLine); // FALSE = don't add the "\n" at the end.
229         if (iRet)
230         {
231             Scierror(999, _("%s: Error while writing in file: disk full or deleted file.\n"), "mprintf");
232             return types::Function::Error;
233         }
234     }
235
236     for (int i = 0; i < nbrOfLines; i++)
237     {
238         FREE(wcsStringToWrite[i]);
239     }
240
241     FREE(wcsStringToWrite);
242     delete[] pArgs;
243
244     return types::Function::OK;
245 }
246 /*--------------------------------------------------------------------------*/