mfprintf, mfscanf, mscanf, msscanf added.
[scilab.git] / scilab / modules / fileio / src / c / do_xxscanf.c
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) INRIA
4  * ...
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 /*--------------------------------------------------------------------------*/
14 #if defined(__linux__)
15 #define _GNU_SOURCE /* Bug 5673 fix: avoid dependency on GLIBC_2.7 */
16 #endif
17
18 #include <stdio.h>
19 #include <ctype.h>  /* isdigit */
20 #include <string.h>
21 #include "BOOL.h"
22 #include "MALLOC.h"
23 #include "do_xxscanf.h"
24 #include "Scierror.h"
25 #include "localization.h"
26 #include "do_xxprintf.h"
27 #include "core_math.h"
28 /*--------------------------------------------------------------------------*/
29 typedef int (*XXSCANF)(FILE *, wchar_t *,...);
30 typedef int (*FLUSH)(FILE *);
31 /*--------------------------------------------------------------------------*/
32 static void set_xxscanf(FILE *fp,XXSCANF *xxscanf,wchar_t **target,wchar_t **strv)
33 {
34         if (fp == (FILE *) 0)
35         {
36                 *target = *strv;
37                 *xxscanf = (XXSCANF) swscanf;
38         }
39         else
40         {
41                 *target = (wchar_t *) fp;
42                 *xxscanf = (XXSCANF) fwscanf;
43         }
44 }
45 /*--------------------------------------------------------------------------*/
46 int do_xxscanf (wchar_t *fname, FILE *fp, wchar_t *format, int *nargs, wchar_t *strv, int *retval, rec_entry *buf, sfdir *type)
47 {
48         int nc[MAXSCAN];
49         int n_directive_count=0;
50         int i=0;
51         int l_flag=0;
52         int h_flag=0;
53         int width_flag=0;
54         int width_val=0;
55         int ignore_flag=0;
56         int str_width_flag=0;
57         int num_conversion = -1;
58         void *ptrtab[MAXSCAN];
59         wchar_t sformat[MAX_STR];
60         wchar_t backupcurrrentchar;
61         wchar_t directive;
62         wchar_t *p=NULL;
63         wchar_t *p1=NULL;
64         wchar_t *target=NULL;
65         wchar_t *sval=NULL;
66         register wchar_t *currentchar=NULL;
67
68         XXSCANF xxscanf;
69
70         set_xxscanf(fp,&xxscanf,&target,&strv);
71         currentchar = format;
72         *retval = 0;
73
74         while (TRUE)
75         {
76                 /* scanf */
77                 p=currentchar;
78                 while (*currentchar != '%' && *currentchar != '\0' ) currentchar++;
79                 if ( *currentchar == '%' && *(currentchar+1) == '%' )
80                 {
81                         currentchar=currentchar+2;
82                         while (*currentchar != '%' && *currentchar != '\0' ) currentchar++;
83                 }
84
85                 if (*currentchar == 0)
86                 {
87                         break ;
88                 }
89
90                 currentchar++;
91                 p1 = currentchar - 1;
92
93                 while ( isdigit(((int)*currentchar)) ) currentchar++;
94
95                 width_flag =0;
96
97                 if ( p1+1 != currentchar )
98                 {
99                         wchar_t w= *currentchar;
100                         *currentchar='\0';
101                         width_flag = 1;
102                         swscanf(p1+1,L"%d",&width_val);
103                         *currentchar=w;
104                 }
105
106                 ignore_flag=0;
107
108                 if (*currentchar == '*')
109                 {
110                         ignore_flag = 1;
111                         currentchar++;
112                 }
113                 else
114                 {
115                         l_flag = h_flag = 0;
116                 }
117
118                 if (*currentchar == 'l')
119                 {
120                         currentchar++;
121                         l_flag = 1;
122                 }
123                 else if (*currentchar == 'h')
124                 {
125                         currentchar++;
126                         h_flag = 1;
127                 }
128
129                 /* directive points to the scan directive  */
130
131                 directive = *currentchar++;
132
133                 if ( directive == '[' )
134                 {
135                         wchar_t *currentchar1=currentchar--;
136                         while ( *currentchar1 != '\0' && *currentchar1 != ']') currentchar1++;
137
138                         if ( *currentchar1 == '\0')
139                         {
140                                 Scierror(998,_("%s: An error occurred: %s\n"),fname,_("unclosed [ directive."));
141                                 return DO_XXPRINTF_RET_BUG;
142                         }
143
144                         if ( currentchar1 == currentchar +1 || wcsncmp(currentchar,"[^]",3)==0 )
145                         {
146                                 currentchar1++;
147                                 while ( *currentchar1 != '\0' && *currentchar1 != ']') currentchar1++;
148
149                                 if ( *currentchar1 == '\0')
150                                 {
151                                         Scierror(998,_("%s: An error occurred: %s\n"),fname,_("unclosed [ directive."));
152                                         return DO_XXPRINTF_RET_BUG;
153                                 }
154                         }
155
156                         directive = *currentchar1++;
157                         currentchar=currentchar1;
158                 }
159
160                 backupcurrrentchar = *currentchar;
161
162                 if ( ignore_flag != 1)
163                 {
164                         num_conversion++;
165
166                         if ( num_conversion >= MAXSCAN )
167                         {
168                                 Scierror(998,_("%s: An error occurred: too many (> %d) conversion required.\n"),fname,MAXSCAN);
169                                 return DO_XXPRINTF_RET_BUG;
170                         }
171
172                         switch (directive )
173                         {
174                         case ']':
175                                 /*if (width_flag == 0 )*/ str_width_flag = 1;
176
177                                 if (width_flag == 1 && width_val > MAX_STR-1 )
178                                 {
179                                         Scierror(998,_("%s: An error occurred: field %d is too long (> %d) for %%[ directive.\n"),fname,width_val,MAX_STR-1);
180                                         return DO_XXPRINTF_RET_BUG;
181                                 }
182
183                                 if ((buf[num_conversion].c=MALLOC(MAX_STR))==NULL) return DO_XXPRINTF_MEM_LACK;
184                                 ptrtab[num_conversion] =  buf[num_conversion].c;
185                                 type[num_conversion] = SF_S;
186                                 break;
187
188                         case 's':
189                                 if (/*l_flag +*/ h_flag)
190                                 {
191                                         Scierror(998,_("%s: An error occurred: %s\n"),fname,_("Bad conversion."));
192                                         return DO_XXPRINTF_RET_BUG;
193                                 }
194
195                                 /*if (width_flag == 0 )*/ str_width_flag = 1;
196                                 if (width_flag == 1 && width_val > MAX_STR-1 )
197                                 {
198                                         Scierror(998,_("%s: An error occurred: field %d is too long (< %d) for %%s directive.\n"),fname,width_val,MAX_STR-1);
199                                         return DO_XXPRINTF_RET_BUG;
200                                 }
201
202                                 if ((buf[num_conversion].c=MALLOC(MAX_STR))==NULL) return DO_XXPRINTF_MEM_LACK;
203
204                                 ptrtab[num_conversion] =  buf[num_conversion].c;
205                                 type[num_conversion] = SF_S;
206                                 break;
207
208                         case 'c':
209                                 if (/*l_flag +*/ h_flag)
210                                 {
211                                         Scierror(998,_("%s: An error occurred: %s\n"),fname,_("Bad conversion."));
212                                         return DO_XXPRINTF_RET_BUG;
213                                 }
214                 str_width_flag = 1;
215                                 if ( width_flag == 1 ) nc[num_conversion ] = width_val;
216                                 else nc[num_conversion ] = 1;
217
218                                 if (width_flag == 1 && width_val > MAX_STR-1 )
219                                 {
220                                         Scierror(998,_("%s: An error occurred: field %d is too long (< %d) for %%c directive.\n"),fname,width_val,MAX_STR-1);
221                                         return DO_XXPRINTF_RET_BUG;
222                                 }
223
224                                 if ((buf[num_conversion].c=MALLOC(MAX_STR))==NULL) return DO_XXPRINTF_MEM_LACK;
225
226                                 ptrtab[num_conversion] =  buf[num_conversion].c;
227                                 type[num_conversion] = SF_C;
228                                 break;
229
230                         case 'o': case 'u': case 'x': case 'X':
231                                 if ( l_flag )
232                                 {
233                                         ptrtab[num_conversion] =  &buf[num_conversion].lui;
234                                         type[num_conversion] = SF_LUI;
235                                 }
236                                 else if ( h_flag)
237                                 {
238                                         ptrtab[num_conversion] =  &buf[num_conversion].sui;
239                                         type[num_conversion] = SF_SUI;
240                                 }
241                                 else
242                                 {
243                                         ptrtab[num_conversion] =  &buf[num_conversion].ui;
244                                         type[num_conversion] = SF_UI;
245                                 }
246                                 break;
247
248                         case 'D':
249                                 ptrtab[num_conversion] =  &buf[num_conversion].li;
250                                 type[num_conversion] = SF_LI;
251                                 break;
252
253                         case 'n':
254                                 n_directive_count++;
255
256                         case 'i': case 'd':
257                                 if ( l_flag )
258                                 {
259                                         ptrtab[num_conversion] =  &buf[num_conversion].li;
260                                         type[num_conversion] = SF_LI;
261                                 }
262                                 else if ( h_flag)
263                                 {
264                                         ptrtab[num_conversion] =  &buf[num_conversion].si;
265                                         type[num_conversion] = SF_SI;
266                                 }
267                                 else
268                                 {
269                                         ptrtab[num_conversion] =  &buf[num_conversion].i;
270                                         type[num_conversion] = SF_I;
271                                 }
272                                 break;
273
274                         case 'e': case 'f': case 'g': case 'E': case 'G':
275                                 if (h_flag)
276                                 {
277                                         Scierror(998,_("%s: An error occurred: %s\n"),fname,_("Bad conversion."));
278                                         return DO_XXPRINTF_RET_BUG;
279                                 }
280                                 else if (l_flag)
281                                 {
282                                         ptrtab[num_conversion] =  &buf[num_conversion].lf;
283                                         type[num_conversion] = SF_LF;
284                                 }
285                                 else
286                                 {
287                                         ptrtab[num_conversion] =  &buf[num_conversion].f;
288                                         type[num_conversion] = SF_F;
289                                 }
290                                 break;
291
292                         default:
293                                 Scierror(998,_("%s: An error occurred: %s\n"),fname,_("Bad conversion."));
294                                 return DO_XXPRINTF_RET_BUG;
295                                 break;
296                         }
297                         *currentchar = backupcurrrentchar;
298                 }
299         }
300
301         if ( str_width_flag == 1)
302         {
303                 wchar_t *f1=format;
304                 wchar_t *f2=sformat;
305                 wchar_t *slast = sformat + MAX_STR - 1 - 4;
306
307         int bFirst = 1;
308                 while ( *f1 != '\0'  )
309                 {
310                         int n;
311                         if(*(f1) == '%')
312                         {
313                 bFirst = 1;
314                         }
315                         *f2++ = *f1++;
316             if(bFirst && ( *(f1) == 's'  || *(f1) == '[' || *(f1) == 'c'))
317             {
318                 bFirst = 0;
319                 if(*(f1-1) != 'l' && *(f1-1) != 'L')
320                 {
321                     *f2++  = L'l';
322                 }
323             }
324                         if( (*(f1) == 's' || *(f1) == '[') 
325                             && 
326                             (   (*(f1-1) == '%') 
327                                 || 
328                     ((*(f1-1) == 'l' || *(f1-1) == 'L') && (*(f1-2) == '%'))
329                 )
330               )
331                         {
332                             f2--;
333                                 n=swprintf(f2,MAX_STR-1,L"%d%c",MAX_STR-1,L'l');
334                                 f2 += n;
335                                 *f2++ = *f1++;
336                         }
337
338                         if ( f2 == slast )
339                         {
340                                 Scierror(998,_("%s: An error occurred: format is too long (> %d).\n"),fname,MAX_STR-1);
341                                 return DO_XXPRINTF_RET_BUG;
342                         }
343                 }
344
345                 *f2='\0';
346                 format = sformat;
347         }
348
349         *retval = (*xxscanf) ((VPTR) target,format,
350                 ptrtab[0],ptrtab[1],ptrtab[2],ptrtab[3],ptrtab[4],ptrtab[5],ptrtab[6],ptrtab[7],ptrtab[8],ptrtab[9],
351                 ptrtab[10],ptrtab[11],ptrtab[12],ptrtab[13],ptrtab[14],ptrtab[15],ptrtab[16],ptrtab[17],ptrtab[18],ptrtab[19],
352                 ptrtab[20],ptrtab[21],ptrtab[22],ptrtab[23],ptrtab[24],ptrtab[25],ptrtab[26],ptrtab[27],ptrtab[28],ptrtab[29],
353                 ptrtab[30],ptrtab[31],ptrtab[32],ptrtab[33],ptrtab[34],ptrtab[35],ptrtab[36],ptrtab[37],ptrtab[38],ptrtab[39],
354                 ptrtab[40],ptrtab[41],ptrtab[42],ptrtab[43],ptrtab[44],ptrtab[45],ptrtab[46],ptrtab[47],ptrtab[48],ptrtab[49],
355                 ptrtab[50],ptrtab[51],ptrtab[52],ptrtab[53],ptrtab[54],ptrtab[55],ptrtab[56],ptrtab[57],ptrtab[58],ptrtab[59],
356                 ptrtab[60],ptrtab[61],ptrtab[62],ptrtab[63],ptrtab[64],ptrtab[65],ptrtab[66],ptrtab[67],ptrtab[68],ptrtab[69],
357                 ptrtab[70],ptrtab[71],ptrtab[72],ptrtab[73],ptrtab[74],ptrtab[75],ptrtab[76],ptrtab[77],ptrtab[78],ptrtab[79],
358                 ptrtab[80],ptrtab[81],ptrtab[82],ptrtab[83],ptrtab[84],ptrtab[85],ptrtab[86],ptrtab[87],ptrtab[88],ptrtab[89],
359                 ptrtab[90],ptrtab[91],ptrtab[92],ptrtab[93],ptrtab[94],ptrtab[95],ptrtab[96],ptrtab[97],ptrtab[98],ptrtab[MAXSCAN-1]);
360
361         *nargs = Min(num_conversion+1,Max(*retval+n_directive_count,0));
362
363         for ( i=1 ; i <= *nargs ; i++)
364         {
365                 if ( type[i-1]  == SF_C )
366                 {
367                         sval=(wchar_t *) ptrtab[i-1];
368                         sval[nc[i-1]]='\0';
369                 }
370         }
371
372         return 0;
373 }
374 /*--------------------------------------------------------------------------*/
375