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