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