bug 4833 fixed - msprintf() interpreted '\n' as a carriage return even if '\n' is...
[scilab.git] / scilab / modules / output_stream / sci_gateway / c / sci_msprintf.c
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) INRIA
4 * Copyright (C) DIGITEO - 2010-2011 - Allan CORNET
5
6 * This file must be used under the terms of the CeCILL.
7 * This source file is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution.  The terms
9 * are also available at    
10 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11 *
12 */
13 #include "gw_output_stream.h"
14 #include "api_scilab.h"
15 #include "Scierror.h"
16 #include "MALLOC.h"
17 #include "stack-c.h"
18 #include "do_xxprintf.h"
19 #include "localization.h"
20 #include "freeArrayOfString.h"
21 #include "strsubst.h"
22 /*--------------------------------------------------------------------------*/
23 #define TAB_CHAR_SEARCHED "\\t"
24 #define TAB_CHAR_REPLACED "\t"
25 #define PERCENT_CHAR '%'
26 #define SPLIT_ON_CR_IN_FORMAT "<CR_IN_FORMAT>"
27 #define CR_IN_FORMAT "\\n"
28 #define EMPTY_CHAR '\0'
29 /*--------------------------------------------------------------------------*/
30 int sci_msprintf(char *fname, unsigned long fname_len)
31 {
32     SciErr sciErr;
33     int iType = 0;
34     int *piAddressVarOne = NULL;
35     char *ptrFormat = NULL;
36     int K = 0;
37     int i = 0;
38     int lenghtFormat = 0;
39     int NumberPercent = 0;
40     int NumberCols = 0;
41     int nmax = 0;
42     int cat_to_last = 0;
43     int ll = 0;
44     char **pStrs = NULL;
45     char **pOutputStrings = NULL;
46     char *pStrTmp = NULL;
47     char *pStrTmp1 = NULL;
48     int lcount = 0;
49     int rval = 0;
50     int blk = 200;
51
52     int k = 0;
53     int mOut = 0;
54     int nOut = 0;
55     int lenghtSplitChar = (int)strlen(SPLIT_ON_CR_IN_FORMAT);
56
57     Nbvars = 0;
58     CheckRhs(1, 1000);
59     CheckLhs(0, 1);
60
61     for (K = 2; K <= Rhs; K++)
62     {
63         int iTypeK = 0;
64         int *piAddressVarK = NULL;
65
66         sciErr = getVarAddressFromPosition(pvApiCtx, K, &piAddressVarK);
67         if(sciErr.iErr)
68         {
69             printError(&sciErr, 0);
70             return 0;
71         }
72
73         sciErr = getVarType(pvApiCtx, piAddressVarK, &iTypeK);
74         if(sciErr.iErr)
75         {
76             printError(&sciErr, 0);
77             return 0;
78         }
79
80         if ( (iTypeK != sci_matrix) && (iTypeK != sci_strings) )
81         {
82             OverLoad(K);
83             return 0;
84         }
85     }
86
87     sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddressVarOne);
88     if(sciErr.iErr)
89     {
90         printError(&sciErr, 0);
91         return 0;
92     }
93
94     sciErr = getVarType(pvApiCtx, piAddressVarOne, &iType);
95     if(sciErr.iErr)
96     {
97         printError(&sciErr, 0);
98         return 0;
99     }
100
101     if (checkVarDimension(pvApiCtx, piAddressVarOne, 1, 1) != 1)
102     {
103         Scierror(999,_("%s: Wrong size for input argument #%d: A string expected.\n"), fname, 1);
104         return 0;
105     }
106
107     if (getAllocatedSingleString(pvApiCtx, piAddressVarOne, &ptrFormat))
108     {
109         Scierror(999,_("%s: Memory allocation error.\n"), fname);
110         return 0;
111     }
112
113     if (ptrFormat == NULL)
114     {
115         Scierror(999,_("%s: Memory allocation error.\n"), fname);
116         return 0;
117     }
118     else
119     {
120         char *pFormatTmp = strsub(ptrFormat, TAB_CHAR_SEARCHED, TAB_CHAR_REPLACED);
121         if (pFormatTmp)
122         {
123             freeAllocatedSingleString(ptrFormat);
124             ptrFormat = strsub(pFormatTmp, CR_IN_FORMAT, SPLIT_ON_CR_IN_FORMAT);
125             FREE(pFormatTmp);
126             if (ptrFormat == NULL)
127             {
128                 Scierror(999,_("%s: Memory allocation error.\n"), fname);
129                 return 0;
130             }
131         }
132         else
133         {
134             Scierror(999,_("%s: Memory allocation error.\n"), fname);
135             return 0;
136         }
137     }
138
139     lenghtFormat = (int)strlen(ptrFormat);
140     for(i = 0; i < lenghtFormat; i++)
141     {
142         if (ptrFormat[i] == PERCENT_CHAR)
143         {
144             NumberPercent++;
145             if ( (i+1 < lenghtFormat) && (ptrFormat[i+1] == PERCENT_CHAR))
146             {
147                 NumberPercent--;
148                 i++;
149             }
150         }
151     }
152
153     if ( (Rhs - 1) > NumberPercent )
154     {
155         if (ptrFormat)
156         {
157             FREE(ptrFormat);
158             ptrFormat = NULL;
159         }
160
161         Scierror(999,_("%s: Wrong number of input arguments: at most %d expected.\n"), fname, NumberPercent);
162         return 0;
163     }
164
165     if( Rhs > 1 )
166     {
167         for( i = 2 ; i <= Rhs ; i++ )
168         {
169             int iRows = 0;
170             int iCols = 0;
171             int *piAddressVarI = NULL;
172
173             sciErr = getVarAddressFromPosition(pvApiCtx, i, &piAddressVarI);
174             if(sciErr.iErr)
175             {
176                 printError(&sciErr, 0);
177                 return 0;
178             }
179
180             sciErr = getVarDimension(pvApiCtx, piAddressVarI, &iRows, &iCols);
181             if(sciErr.iErr)
182             {
183                 printError(&sciErr, 0);
184                 return 0;
185             }
186             NumberCols += iCols;
187         }
188     }
189
190     if ( NumberCols != NumberPercent )
191     {
192         if (ptrFormat)
193         {
194             FREE(ptrFormat);
195             ptrFormat = NULL;
196         }
197         Scierror(999,_("%s: Wrong number of input arguments: data doesn't fit with format.\n"), fname);
198         return 0;
199     }
200
201     mOut = 0; /* output line counter */
202     nmax = 0;
203     pOutputStrings = NULL;
204     lcount = 1;
205     cat_to_last = 0;
206
207     while (1)
208     {
209         if ((rval = do_xxprintf("msprintf",(FILE *) 0, ptrFormat, Rhs, 1, lcount, (char **) &pStrs)) < 0) 
210         {
211             break;
212         }
213
214         lcount++;
215         pStrTmp = (char *)pStrs;
216         if (pStrTmp == NULL)
217         {
218             if (ptrFormat)
219             {
220                 FREE(ptrFormat);
221                 ptrFormat = NULL;
222             }
223
224             Scierror(999,_("%s: Wrong value of input argument %d: data doesn't fit with format.\n"),fname,1);
225             return 0;
226         }
227
228         pStrTmp1 = pStrTmp;
229         while (*pStrTmp != '\0')  
230         {
231             if (strncmp(pStrTmp, SPLIT_ON_CR_IN_FORMAT, lenghtSplitChar) ==0) 
232             {
233                 k = (int)(pStrTmp - pStrTmp1);
234                 if (!cat_to_last) 
235                 { 
236                     /*add a new line */
237                     if (mOut == nmax) 
238                     {
239                         nmax += blk;
240                         if (pOutputStrings) 
241                         {
242                             pOutputStrings = (char **) REALLOC(pOutputStrings, nmax * sizeof(char **));
243                         } 
244                         else 
245                         {
246                             pOutputStrings = (char **) MALLOC(nmax * sizeof(char **));
247                         }
248
249                         if (pOutputStrings == NULL) 
250                         {
251                             if (ptrFormat)
252                             {
253                                 FREE(ptrFormat);
254                                 ptrFormat = NULL;
255                             }
256
257                             Scierror(999,_("%s: No more memory.\n"),fname);
258                             return 0;
259                         }
260                     }
261
262                     pOutputStrings[mOut] = (char*)MALLOC((k+1) * sizeof(char));
263                     if (pOutputStrings[mOut] == NULL) 
264                     {
265                         if (ptrFormat)
266                         {
267                             FREE(ptrFormat);
268                             ptrFormat = NULL;
269                         }
270
271                         Scierror(999,_("%s: No more memory.\n"),fname);
272                         return 0;
273                     }
274                     strncpy(pOutputStrings[mOut], pStrTmp1, k);
275                     pOutputStrings[mOut][k] = EMPTY_CHAR;
276                     mOut++;
277                 }
278                 else 
279                 {
280                     /* cat to previous line */
281                     ll = (int)strlen(pOutputStrings[mOut - 1]);
282                     pOutputStrings[mOut - 1] = (char*)REALLOC(pOutputStrings[mOut - 1], (k + 1 + ll)*sizeof(char));
283                     if (pOutputStrings[mOut - 1] == NULL) 
284                     {
285                         if (ptrFormat)
286                         {
287                             FREE(ptrFormat);
288                             ptrFormat = NULL;
289                         }
290
291                         Scierror(999,_("%s: No more memory.\n"),fname);
292                         return 0;
293                     }
294                     strncpy(&(pOutputStrings[mOut - 1][ll]), pStrTmp1, k);
295                     pOutputStrings[mOut - 1][k + ll] = EMPTY_CHAR;
296                 }
297                 k = 0;
298                 pStrTmp += lenghtSplitChar;
299                 pStrTmp1 = pStrTmp;
300                 cat_to_last = 0;
301             }
302             else
303             {
304                 pStrTmp++;
305             }
306         }
307         k = (int)(pStrTmp - pStrTmp1);
308         if (k > 0) 
309         {
310             if ((!cat_to_last) || (mOut == 0)) 
311             { 
312                 /*add a new line */
313                 if (mOut == nmax) 
314                 {
315                     nmax += blk;
316                     if (pOutputStrings)
317                     {
318                         pOutputStrings = (char **) REALLOC(pOutputStrings, nmax*sizeof(char **));
319                         if (pOutputStrings == NULL) 
320                         {
321                             if (ptrFormat)
322                             {
323                                 FREE(ptrFormat);
324                                 ptrFormat = NULL;
325                             }
326
327                             Scierror(999,_("%s: No more memory.\n"),fname);
328                             return 0;
329                         }
330                     }
331                     else
332                     {
333                         pOutputStrings = (char **) MALLOC(nmax * sizeof(char **));
334                         if (pOutputStrings == NULL) 
335                         {
336                             if (ptrFormat)
337                             {
338                                 FREE(ptrFormat);
339                                 ptrFormat = NULL;
340                             }
341
342                             Scierror(999,_("%s: No more memory.\n"),fname);
343                             return 0;
344                         }
345                     }
346                 }
347
348                 pOutputStrings[mOut] = (char*) MALLOC((k + 1) * sizeof(char));
349                 if (pOutputStrings[mOut] == NULL) 
350                 {
351                     if (ptrFormat)
352                     {
353                         FREE(ptrFormat);
354                         ptrFormat = NULL;
355                     }
356
357                     Scierror(999,_("%s: No more memory.\n"), fname);
358                     return 0;
359                 }
360                 strncpy(pOutputStrings[mOut], pStrTmp1, k);
361                 pOutputStrings[mOut][k] = EMPTY_CHAR;
362                 mOut++;
363             }
364             else 
365             { 
366                 /* cat to previous line */
367                 ll = (int)strlen(pOutputStrings[mOut - 1]);
368                 pOutputStrings[mOut - 1] = (char*)REALLOC(pOutputStrings[mOut - 1], (k + 1 + ll) * sizeof(char));
369                 if (pOutputStrings[mOut - 1] == NULL) 
370                 {
371                     if (ptrFormat)
372                     {
373                         FREE(ptrFormat);
374                         ptrFormat = NULL;
375                     }
376
377                     Scierror(999,_("%s: No more memory.\n"),fname);
378                     return 0;
379                 }
380                 strncpy(&(pOutputStrings[mOut - 1][ll]), pStrTmp1, k);
381                 pOutputStrings[mOut - 1][k + ll] = EMPTY_CHAR;
382             }
383         }
384
385         if (strncmp(pStrTmp - lenghtSplitChar, SPLIT_ON_CR_IN_FORMAT, lenghtSplitChar) != 0) 
386         {
387             cat_to_last = 1;
388         }
389         if (Rhs == 1) break;
390
391     }
392
393     if (ptrFormat)
394     {
395         FREE(ptrFormat);
396         ptrFormat = NULL;
397     }
398
399     if (rval == RET_BUG) return 0;
400
401     /* Create a Scilab String */
402     nOut = 1;
403     sciErr = createMatrixOfString(pvApiCtx, Rhs + 1 , mOut, nOut, pOutputStrings);
404
405     /* lstr must not be freed */
406     freeArrayOfString(pOutputStrings, mOut * nOut);
407     if(sciErr.iErr)
408     {
409         printError(&sciErr, 0);
410     }
411     else
412     {
413         LhsVar(1) = Rhs + 1;
414         PutLhsVar();
415     }
416     return 0;
417 }
418 /*--------------------------------------------------------------------------*/