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