e1cb56d6012e7c5a8d652b5ec2a1146dce00289d
[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 *, char *,...);
30 typedef int (*FLUSH)(FILE *);
31 /*--------------------------------------------------------------------------*/
32 static void set_xxscanf(FILE *fp,XXSCANF *xxscanf,char **target,char **strv)
33 {
34         if (fp == (FILE *) 0)
35         {
36                 *target = *strv;
37                 *xxscanf = (XXSCANF) sscanf;
38         }
39         else
40         {
41                 *target = (char *) fp;
42                 *xxscanf = (XXSCANF) fscanf;
43         }
44 }
45 /*--------------------------------------------------------------------------*/
46 int do_xxscanf (char *fname, FILE *fp, char *format, int *nargs, char *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         char sformat[MAX_STR];
60         char backupcurrrentchar;
61         char directive;
62         char *p=NULL;
63         char *p1=NULL;
64         char *target=NULL;
65         char *sval=NULL;
66         register char *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                         char w= *currentchar;
100                         *currentchar='\0';
101                         width_flag = 1;
102                         sscanf(p1+1,"%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                         char *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 || strncmp(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
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                 char *f1=format;
304                 char *f2=sformat;
305                 char *slast = sformat + MAX_STR - 1 - 4;
306
307                 while ( *f1 != '\0'  )
308                 {
309                         int n;
310                         *f2++ = *f1++;
311
312                         if ( *(f1-1) == '%' && ( *(f1) == 's'  || *(f1) == '['))
313                         {
314                                 n=sprintf(f2,"%d",MAX_STR-1);
315                                 f2 += n;
316                                 *f2++ = *f1++;
317                         }
318
319                         if ( f2 == slast )
320                         {
321                                 Scierror(998,_("%s: An error occurred: format is too long (> %d).\n"),fname,MAX_STR-1);
322                                 return DO_XXPRINTF_RET_BUG;
323                         }
324                 }
325
326                 *f2='\0';
327                 format = sformat;
328         }
329
330         *retval = (*xxscanf) ((VPTR) target,format,
331                 ptrtab[0],ptrtab[1],ptrtab[2],ptrtab[3],ptrtab[4],ptrtab[5],ptrtab[6],ptrtab[7],ptrtab[8],ptrtab[9],
332                 ptrtab[10],ptrtab[11],ptrtab[12],ptrtab[13],ptrtab[14],ptrtab[15],ptrtab[16],ptrtab[17],ptrtab[18],ptrtab[19],
333                 ptrtab[20],ptrtab[21],ptrtab[22],ptrtab[23],ptrtab[24],ptrtab[25],ptrtab[26],ptrtab[27],ptrtab[28],ptrtab[29],
334                 ptrtab[30],ptrtab[31],ptrtab[32],ptrtab[33],ptrtab[34],ptrtab[35],ptrtab[36],ptrtab[37],ptrtab[38],ptrtab[39],
335                 ptrtab[40],ptrtab[41],ptrtab[42],ptrtab[43],ptrtab[44],ptrtab[45],ptrtab[46],ptrtab[47],ptrtab[48],ptrtab[49],
336                 ptrtab[50],ptrtab[51],ptrtab[52],ptrtab[53],ptrtab[54],ptrtab[55],ptrtab[56],ptrtab[57],ptrtab[58],ptrtab[59],
337                 ptrtab[60],ptrtab[61],ptrtab[62],ptrtab[63],ptrtab[64],ptrtab[65],ptrtab[66],ptrtab[67],ptrtab[68],ptrtab[69],
338                 ptrtab[70],ptrtab[71],ptrtab[72],ptrtab[73],ptrtab[74],ptrtab[75],ptrtab[76],ptrtab[77],ptrtab[78],ptrtab[79],
339                 ptrtab[80],ptrtab[81],ptrtab[82],ptrtab[83],ptrtab[84],ptrtab[85],ptrtab[86],ptrtab[87],ptrtab[88],ptrtab[89],
340                 ptrtab[90],ptrtab[91],ptrtab[92],ptrtab[93],ptrtab[94],ptrtab[95],ptrtab[96],ptrtab[97],ptrtab[98],ptrtab[MAXSCAN-1]);
341
342         *nargs = Min(num_conversion+1,Max(*retval+n_directive_count,0));
343
344         for ( i=1 ; i <= *nargs ; i++)
345         {
346                 if ( type[i-1]  == SF_C )
347                 {
348                         sval=(char *) ptrtab[i-1];
349                         sval[nc[i-1]]='\0';
350                 }
351         }
352
353         return 0;
354 }
355 /*--------------------------------------------------------------------------*/
356