1 
2 /*
3  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
4  * Copyright (C) 2005-2008 - INRIA - Serge STEER <serge.steer@inria.fr>
5  * Copyright (C) 2005-2008 - INRIA - Pierrick MODE
6  *
7  * Copyright (C) 2012 - 2016 - Scilab Enterprises
8  *
9  * This file is hereby licensed under the terms of the GNU GPL v2.0,
10  * pursuant to article 5.3.4 of the CeCILL v.2.1.
11  * This file was originally licensed under the terms of the CeCILL v2.1,
12  * and continues to be available under such terms.
13  * For more information, see the COPYING file which you should have received
14  * along with this program.
15  *
16  */
17 
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include "core_math.h"
22 #include "sci_malloc.h" /* MALLOC */
23 #include "sciprint.h"
24 #include "returnanan.h"
25 #include "xls.h"
26 #include "mseek.h"
27 #include "mtell.h"
28 #include "mget.h"
29 /*------------------------------------------------------------------*/
30 #define  typ_short "s"
31 #define  typ_ushort "us"
32 #define  typ_char "c"
33 #define  typ_uchar "uc"
34 #define  typ_double "d"
35 #define  typ_int "i"
36 /*------------------------------------------------------------------*/
37 extern int ripole(char *inputfile, char *outputfile, int debug, int verbose);
38 /*------------------------------------------------------------------*/
39 /*Prototype*/
40 static double NumFromRk2(long rk);
41 static void getBoundsheets(int * fd, char ***Sheetnames, int** Abspos, int *nsheets, long long *cur_pos, int *err);
42 static void getSST(int *fd, short Len, int BIFF, int *ns, char ***sst, int *err);
43 static void getBOF(int *fd , int* Data, int *err);
44 static void getString(int *fd, short *count, short *Len, int flag, char **str, int *err);
45 
46 /**
47  ** Bruno : Defined but not used ... so what !!!!!!!!
48  static int get_oleheader(int *fd);
49 **/
50 /*------------------------------------------------------------------*/
xls_read(int * fd,int * cur_pos,double ** data,int ** chainesind,int * N,int * M,int * err)51 void xls_read(int *fd, int *cur_pos, double **data, int **chainesind, int *N, int *M, int *err)
52 {
53     /*---------------Declaration Des Variables*--------------------*/
54     unsigned short Opcode = 0, Len = 0;   /*Code Operationnel et Longueur du tag a lire*/
55     double *valeur = NULL;    /*Tableau Recapitulatif (Final) des valeurs de la feuille Excel*/
56     long long pos = 0;
57 
58     int one = 1;
59     int three = 3;
60 
61     int i = 0;  /*Variables de boucle*/
62     int hauteur = 0, longueur = 0, capacite = 0;   /*Hauteur, longueur de la feuille,  */
63     /*int taille = 0; Nombre de types de caract�ers a enregistrer*/
64     char *sheetname = NULL;   /*Nom de la feuille*/
65     int rkvalue = 0; /*RK value*/
66     /*for RK */
67     unsigned short row = 0, col = 0, xf = 0;/*Index to row, to column, and to XF record*/
68     /*for MULRK */
69     unsigned short ixfe = 0;
70     short colFirst = 0, colLast = 0, ncol = 0; /*Index to rox, to first column (fc)*/
71     /* for LABELSST */
72     short labelsst1[3];
73     int indsst = 0; /*Index to SST record*/
74     /* for DIMENSIONS */
75     int f_row = 0, l_row = 0;
76     unsigned short f_col = 0, l_col = 0, notused = 0;
77     /* for FORMULA */
78     double resultat = 0.;/*Result of the formula*/
79     short optionflag = 0;/*Option flags*/
80     int formula_notused = 0; /*Not used*/
81     double NaN = C2F(returnanan)();
82 
83     int BOFData[7]; /*[BIFF  Version DataType Identifier Year HistoryFlags LowestXlsVersion]*/
84     /* initialization of pointers corresponding to malloc's */
85     valeur = (double *)NULL;
86     sheetname = (char *)NULL;
87     *chainesind = (int *) NULL;
88     *err = 0;
89 
90     *err = mseek(*fd, (long long) * cur_pos, SEEK_SET);
91     if (*err > 0)
92     {
93         goto ErrL;
94     }
95 
96     /* first record should be a BOF */
97     getBOF(fd , BOFData, err);
98 
99     if (*err > 0)
100     {
101         return;
102     }
103     if (BOFData[0] < 0) /* not a BOF */
104     {
105         *err = 2;
106         return;
107     }
108     if (BOFData[0] != 8)   /* not a BIFF8 */
109     {
110         *err = 3;
111         return;
112     }
113 
114     pos = mtell(*fd);
115     if (pos < 0)
116     {
117         *err = 2;
118         goto ErrL;
119     }
120 
121     while (1)
122     {
123         *err = mseek(*fd, pos, SEEK_SET);
124         if (*err > 0)
125         {
126             goto ErrL;
127         }
128         /*Enregistrement de l'Opcode et de la Len du tag*/
129         C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
130         if (*err > 0)
131         {
132             goto ErrL;
133         }
134         C2F(mgetnc) (fd, &Len, &one, typ_ushort, err);
135         if (*err > 0)
136         {
137             goto ErrL;
138         }
139         switch (Opcode)
140         {
141             case 10:/*EOF */
142                 *N = hauteur;
143                 *M = longueur;
144                 *data = valeur;
145                 pos = pos + 4 + Len;
146                 *cur_pos = (int)pos;
147                 return;
148             case 638: /*RK*/
149                 C2F(mgetnc) (fd, (void*)&row, &one, typ_ushort, err);
150                 if (*err > 0)
151                 {
152                     goto ErrL;
153                 }
154                 C2F(mgetnc) (fd, (void*)&col, &one, typ_ushort, err);
155                 if (*err > 0)
156                 {
157                     goto ErrL;
158                 }
159                 // Check col and row are in bounds
160                 if ((col >= longueur) || (row >= hauteur))
161                 {
162                     *err = 2;
163                     goto ErrL;
164                 }
165                 C2F(mgetnc) (fd, (void*)&xf , &one, typ_ushort, err);
166                 if (*err > 0)
167                 {
168                     goto ErrL;
169                 }
170                 C2F(mgetnc) (fd, (void*) &rkvalue , &one, typ_int, err);
171                 if (*err > 0)
172                 {
173                     goto ErrL;
174                 }
175                 valeur[col * (hauteur) + row] = NumFromRk2(rkvalue);
176                 break;
177             case 515: /*Number*/
178                 C2F(mgetnc) (fd, (void*)&row, &one, typ_ushort, err);
179                 if (*err > 0)
180                 {
181                     goto ErrL;
182                 }
183                 C2F(mgetnc) (fd, (void*)&col, &one, typ_ushort, err);
184                 if (*err > 0)
185                 {
186                     goto ErrL;
187                 }
188                 // Check col and row are in bounds
189                 if ((col >= longueur) || (row >= hauteur))
190                 {
191                     *err = 2;
192                     goto ErrL;
193                 }
194                 C2F(mgetnc) (fd, (void*)&xf , &one, typ_ushort, err);
195                 if (*err > 0)
196                 {
197                     goto ErrL;
198                 }
199                 C2F(mgetnc) (fd, (void*) &resultat , &one, typ_double, err);
200                 if (*err > 0)
201                 {
202                     goto ErrL;
203                 }
204                 valeur[col * (hauteur) + row] = resultat ;
205                 break;
206 
207             case 189: /*MULRK*/
208                 C2F(mgetnc) (fd, (void*)&row, &one, typ_ushort, err);
209                 if (*err > 0)
210                 {
211                     goto ErrL;
212                 }
213                 C2F(mgetnc) (fd,  (void*)&colFirst, &one, typ_short, err);
214                 if (*err > 0)
215                 {
216                     goto ErrL;
217                 }
218                 // Check col and row are in bounds
219                 if ((colFirst >= longueur) || (row >= hauteur))
220                 {
221                     *err = 2;
222                     goto ErrL;
223                 }
224                 /*List of nc=lc-fc+1  XF/RK structures*/
225                 ncol = (Len - 6) / 6;
226                 for (i = 0; i < ncol; i++)
227                 {
228                     C2F(mgetnc) (fd, (void*) &ixfe, &one, typ_short, err);
229                     if (*err > 0)
230                     {
231                         goto ErrL;
232                     }
233                     C2F(mgetnc) (fd, (void*) &rkvalue, &one, typ_int, err);
234                     if (*err > 0)
235                     {
236                         goto ErrL;
237                     }
238                     valeur[row + (colFirst + i)*hauteur] = NumFromRk2(rkvalue);
239                 }
240 
241                 /*Index of last column*/
242                 C2F(mgetnc) (fd, (void*) &colLast, &one, typ_ushort, err);
243                 if (*err > 0)
244                 {
245                     goto ErrL;
246                 }
247                 break;
248 
249             case 253:/*LABELSST*/
250                 C2F(mgetnc) (fd, (void*) labelsst1, &three, typ_short, err);
251                 if (*err > 0)
252                 {
253                     goto ErrL;
254                 }
255                 C2F(mgetnc) (fd, (void*) &indsst , &one, typ_int, err);
256                 if (*err > 0)
257                 {
258                     goto ErrL;
259                 }
260                 /*Allocation dans le tableau final*/
261                 col = labelsst1[1];
262                 row = labelsst1[0];
263                 // Check col and row are in bounds
264                 if ((col >= longueur) || (row >= hauteur))
265                 {
266                     *err = 2;
267                     goto ErrL;
268                 }
269                 (*chainesind)[col * (hauteur) + row] = indsst + 1;
270                 break;
271             case 512:/* DIMENSIONS*/
272                 C2F(mgetnc) (fd, (void*) &f_row, &one, typ_int, err);
273                 if (*err > 0)
274                 {
275                     goto ErrL;
276                 }
277                 C2F(mgetnc) (fd, (void*) &l_row, &one, typ_int, err);
278                 if (*err > 0)
279                 {
280                     goto ErrL;
281                 }
282                 C2F(mgetnc) (fd, (void*) &f_col, &one, typ_ushort, err);
283                 if (*err > 0)
284                 {
285                     goto ErrL;
286                 }
287                 C2F(mgetnc) (fd, (void*) &l_col, &one, typ_ushort, err);
288                 if (*err > 0)
289                 {
290                     goto ErrL;
291                 }
292                 C2F(mgetnc) (fd, (void*) &notused, &one, typ_ushort, err);
293                 if (*err > 0)
294                 {
295                     goto ErrL;
296                 }
297 
298                 /*Calcul de longueur, hauteur et capacite de la feuille*/
299                 hauteur = l_row; /*-f_row;*/
300                 longueur = l_col; /*-f_col;*/
301                 capacite = hauteur * longueur;
302 
303                 /*Declaration des tableaux de synthese*/
304                 if ((valeur = (void*) MALLOC((capacite + 1) * sizeof(double))) == NULL)
305                 {
306                     goto ErrL;
307                 }
308                 if ((*chainesind = (int *) MALLOC((capacite + 1) * sizeof(int))) == NULL)
309                 {
310                     goto ErrL;
311                 }
312                 for (i = 0; i <= capacite; i++)
313                 {
314                     (*chainesind)[i] = 0;
315                     valeur[i] = NaN;
316                 }
317                 break;
318             case 6:/* FORMULA*/
319                 C2F(mgetnc) (fd, (void*) &row, &one, typ_ushort, err);
320                 if (*err > 0)
321                 {
322                     goto ErrL;
323                 }
324                 C2F(mgetnc) (fd, (void*) &col, &one, typ_ushort, err);
325                 if (*err > 0)
326                 {
327                     goto ErrL;
328                 }
329                 // Check col and row are in bounds
330                 if ((col >= longueur) || (row >= hauteur))
331                 {
332                     *err = 2;
333                     goto ErrL;
334                 }
335                 C2F(mgetnc) (fd, (void*) &xf, &one, typ_ushort, err);
336                 if (*err > 0)
337                 {
338                     goto ErrL;
339                 }
340 
341                 C2F(mgetnc) (fd, (void*) &resultat, &one, typ_double, err);
342                 if (*err > 0)
343                 {
344                     goto ErrL;
345                 }
346 
347                 valeur[(col * hauteur + row)] = resultat;
348 
349                 C2F(mgetnc) (fd, (void*)&optionflag, &one, typ_short, err);
350                 if (*err > 0)
351                 {
352                     goto ErrL;
353                 }
354 
355                 C2F(mgetnc) (fd, (void*) &formula_notused, &one, typ_int, err);
356                 if (*err > 0)
357                 {
358                     goto ErrL;
359                 }
360 
361                 /*Formuled data*/
362 
363                 /*taille=Len-2-2-2-8-2-4;
364                   char formuladata[taille];
365                   C2F(mgetnc) (fd, (void*) formuladata, &taille, typ_char, err);
366                   if (*err > 0) goto ErrL;*/
367 
368                 break;
369         }
370         pos = pos + 4 + Len;
371     }
372 
373     *cur_pos = (int)pos;
374     return;
375 ErrL:
376     {
377         FREE(sheetname);
378         FREE(valeur);
379         FREE(*chainesind);
380         if (*err == 0)
381         {
382             *err = 1;    /* malloc problem */
383         }
384         else
385         {
386             *err = 2;    /* read problem */
387         }
388         return;
389     }
390 }
391 
392 
xls_open(int * err,int * fd,char *** sst,int * ns,char *** Sheetnames,int ** Abspos,int * nsheets)393 void xls_open(int *err, int *fd, char ***sst, int *ns, char ***Sheetnames, int** Abspos, int *nsheets)
394 {
395     /* if opt==1 it is supposed that the current file position is at the beginning of oleheader
396      * if opt==0 it is supposed that the current file position is at the  beginning of workbook stream
397      */
398 
399     /* we suppose that the ole file as a simple structure:
400      * Workbook stream should follows immediately the header
401      * and is strored in sequential sections
402      */
403 
404     /*return *err:
405       0 = OK
406       1 = not an OLE file
407       2 = no Workbook included
408       3 = memory allocation problem
409       4 = incorrect file
410       5 = not a BIFF8 xls file
411      */
412     /*---------------D�claration Des Variables*--------------------*/
413     int k, one = 1;
414     long long cur_pos, init_pos;
415     unsigned short Opcode, Len;
416     /*BOF data*/
417     int BOFData[7]; /*[BIFF  Version DataType Identifier Year HistoryFlags LowestXlsVersion]*/
418     *nsheets = 0;
419     *err = 0;
420     /*---------------D�claration Des Variables*--------------------*/
421 
422     /*  if (get_oleheader(fd)) {
423       *err=1;
424       return;
425       }*/
426     cur_pos = mtell(*fd);
427     init_pos = cur_pos;
428 
429     /* first record should be a BOF */
430     getBOF(fd , BOFData, err);
431     if (*err > 0)
432     {
433         return;
434     }
435 
436     if (BOFData[0] < 0) /* not a BOF */
437     {
438         *err = 4;
439         return;
440     }
441     if (BOFData[0] != 8)   /* not a BIFF8 */
442     {
443         *err = 5;
444         return;
445     }
446 
447     cur_pos = mtell(*fd);
448     if (cur_pos < 0)
449     {
450         goto Err2;
451     }
452 
453     /* loops on records till an EOF is found */
454     while (1)
455     {
456         *err = mseek(*fd, cur_pos, SEEK_SET);
457         if (*err > 0)
458         {
459             goto Err2;
460         }
461         /*Enregistrement de l'Opcode et de la Len du tag*/
462         C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
463         if (*err > 0)
464         {
465             goto Err2;
466         }
467         C2F(mgetnc) (fd, &Len, &one, typ_ushort, err);
468         if (*err > 0)
469         {
470             goto Err2;
471         }
472 
473         switch (Opcode)
474         {
475             case 10: /*EOF*/
476                 cur_pos = cur_pos + 4 + Len;
477                 return ;
478             case 133: /* Boundsheets */
479                 getBoundsheets(fd, Sheetnames, Abspos, nsheets, &cur_pos, err);
480                 for (k = 0; k < *nsheets; k++)
481                 {
482                     (*Abspos)[k] += (int)init_pos;
483                 }
484                 if (*err > 0)
485                 {
486                     return;
487                 }
488                 break;
489             case 252: /* SST= Shared String table*/
490                 getSST(fd, Len, BOFData[0], ns, sst, err);
491                 if (*err > 0)
492                 {
493                     return;
494                 }
495                 cur_pos = cur_pos + 4 + Len;
496                 break;
497             default:
498                 cur_pos = cur_pos + 4 + Len;
499         }
500     }
501 
502 Err2:
503     *err = 4; /* read problem */
504     return;
505 
506 }
507 
NumFromRk2(long rk)508 static double NumFromRk2(long rk)
509 {
510     double num;
511     if (rk & 0x02)
512     {
513         /* int*/
514         num = (double) (rk >> 2);
515     }
516     else
517     {
518         /* hi words of IEEE num*/
519         *((int *)&num + 1) = rk & 0xfffffffc;
520         *((int *)&num) = 0;
521     }
522     if (rk & 0x01)
523         /* divide by 100*/
524     {
525         num /= 100;
526     }
527     return num;
528 }
529 
getBOF(int * fd,int * Data,int * err)530 static void getBOF(int *fd , int* Data, int *err)
531 {
532     /* return Data a vector [BIFF  Version DataType Identifier Year HistoryFlags LowestXlsVersion]
533      * works for BIFF2 to BIFF8 records */
534     int BIFF;
535     short Version;
536     short DataType;
537     short Identifier = 0;
538     short Year = 0;
539     int HistoryFlags = 0;
540     int LowestXlsVersion = 0;
541 
542     unsigned short Opcode;
543     unsigned short Len;
544     int one = 1;
545 
546     C2F(mgetnc) (fd, (void*)&Opcode, &one, typ_ushort, err);
547     if (*err > 0)
548     {
549         return;
550     }
551     C2F(mgetnc) (fd, (void*)&Len, &one, typ_ushort, err);
552     if (*err > 0)
553     {
554         return;
555     }
556 
557     switch (Opcode)
558     {
559         case 2057:     /*Begin of file, BOF for BIFF5 BIFF7 BIFF8 BIFF8X*/
560             C2F(mgetnc) (fd, (void*)&Version, &one, typ_short, err);
561             if (*err > 0)
562             {
563                 return;
564             }
565             C2F(mgetnc) (fd, (void*)&DataType, &one, typ_short, err);
566             if (*err > 0)
567             {
568                 return;
569             }
570             C2F(mgetnc) (fd, (void*)&Identifier, &one, typ_short, err);
571             if (*err > 0)
572             {
573                 return;
574             }
575             C2F(mgetnc) (fd, (void*)&Year, &one, typ_short, err);
576             if (*err > 0)
577             {
578                 return;
579             }
580             if (Len == 16)
581             {
582                 C2F(mgetnc) (fd, (void*)&HistoryFlags, &one, typ_int, err);
583                 if (*err > 0)
584                 {
585                     return;
586                 }
587                 C2F(mgetnc) (fd, (void*)&LowestXlsVersion, &one, typ_int, err);
588                 if (*err > 0)
589                 {
590                     return;
591                 }
592                 BIFF = 8;
593                 if (Version != 1536)
594                 {
595                     return;
596                 }
597             }
598             else
599             {
600                 BIFF = 7;
601             }
602             break;
603         case 1033 : /*Interpr�tation du BIFF4  0409 H*/
604             C2F(mgetnc) (fd, (void*)&Version, &one, typ_short, err);
605             if (*err > 0)
606             {
607                 return;
608             }
609             C2F(mgetnc) (fd, (void*)&DataType, &one, typ_short, err);
610             if (*err > 0)
611             {
612                 return;
613             }
614             BIFF = 4;
615             break;
616         case 521 : /*Interpr�tation du BIFF3  0209 H*/
617             C2F(mgetnc) (fd, (void*)&Version, &one, typ_short, err);
618             if (*err > 0)
619             {
620                 return;
621             }
622             C2F(mgetnc) (fd, (void*)&DataType, &one, typ_short, err);
623             if (*err > 0)
624             {
625                 return;
626             }
627             BIFF = 3;
628             break;
629         case 9 : /*Interpr�tation du BIFF2  0009 H*/
630             C2F(mgetnc) (fd, (void*)&Version, &one, typ_short, err);
631             if (*err > 0)
632             {
633                 return;
634             }
635             C2F(mgetnc) (fd, (void*)&DataType, &one, typ_short, err);
636             if (*err > 0)
637             {
638                 return;
639             }
640             BIFF = 2;
641             break;
642         default:
643             BIFF = -1; /* not a BOF record */
644             Version = 0;
645             DataType = 0;
646     }
647     Data[0] = BIFF;
648     Data[1] = Version;
649     Data[2] = DataType;
650     Data[3] = Identifier;
651     Data[4] = Year;
652     Data[5] = HistoryFlags;
653     Data[6] = LowestXlsVersion;
654 
655 }
656 
getSST(int * fd,short Len,int BIFF,int * ns,char *** sst,int * err)657 static void getSST(int *fd, short Len, int BIFF, int *ns, char ***sst, int *err)
658 {
659     int i = 0, one = 1;
660     /* SST data */
661     int ntot = 0; /*total number of strings */
662     int nm = 0;/*Number of following strings*/
663     short count = 0;
664 
665     *ns = 0;
666     *sst = NULL;
667 
668     if (BIFF == 8)
669     {
670         /*Total number of strings in the workbook*/
671         C2F(mgetnc) (fd, (void*)&ntot, &one, typ_int, err);
672         if (*err > 0)
673         {
674             goto ErrL;
675         }
676         C2F(mgetnc) (fd, (void*)&nm, &one, typ_int, err);
677         if (*err > 0)
678         {
679             goto ErrL;
680         }
681         *ns = nm;
682         count += 8;
683         if (nm != 0)
684         {
685             if ( (*sst = (char **)MALLOC(nm * sizeof(char*))) == NULL)
686             {
687                 goto ErrL;
688             }
689             for (i = 0; i < nm; i++)
690             {
691                 (*sst)[i] = NULL;
692             }
693             for (i = 0; i < nm; i++) /* LOOP ON STRINGS */
694             {
695                 *err = i; /*for debug*/
696                 getString(fd, &count, &Len, 1, &((*sst)[i]), err);
697                 if (*err > 0)
698                 {
699                     goto ErrL;
700                 }
701                 /*printf("i=%d, %s\n",i,(*sst)[i]);*/
702             }
703         }
704     }
705     return;
706 ErrL:
707     if (*sst != NULL)
708     {
709         for (i = 0; i < nm; i++)
710             if ( (*sst)[i] != NULL )
711             {
712                 FREE((*sst)[i]);
713             }
714         FREE(*sst);
715     }
716 
717     if (*err == 0)
718     {
719         *err = 3;    /* malloc problem */
720     }
721     else
722     {
723         *err = 4;    /* read problem */
724     }
725 }
726 
getString(int * fd,short * PosInRecord,short * RecordLen,int flag,char ** str,int * err)727 static void getString(int *fd, short *PosInRecord, short *RecordLen, int flag, char **str, int *err)
728 {
729     short ln = 0;
730     short Opcode = 0;/* to store tag information */
731     int BytesToBeRead = 0, one = 1, strindex = 0;
732     char OptionFlag = 0;
733     int sz = 0; /* for extended string data */
734     short rt = 0;/* for rich string data */
735     int UTFEncoding = 0, extendedString = 0, richString = 0;
736     int j = 0, l1 = 0;
737 
738     *str = (char *)NULL;
739     *err = 0;
740     ln = 0;
741 
742     /*check for continue tag */
743     if (flag && (*PosInRecord == *RecordLen)) /* data limit encountered */
744     {
745         /*check for continue tag */
746         /*lecture de l'Opcode et de la RecordLen du tag*/
747         C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
748         if ((*err > 0) || (Opcode != 60))
749         {
750             goto ErrL;
751         }
752         C2F(mgetnc) (fd, RecordLen, &one, typ_ushort, err);
753         if (*err > 0)
754         {
755             goto ErrL;
756         }
757         *PosInRecord = 0;
758     }
759 
760     /* get the number of characters included in the string (number of bytes or number of couple of bytes) */
761     if (flag)   /* getString called by getSST */
762     {
763         C2F(mgetnc) (fd, (void*)&ln, &one, typ_short, err);
764         if (*err > 0)
765         {
766             goto ErrL;
767         }
768         *PosInRecord += 2;
769     }
770     else   /* getString called by getBoundsheets */
771     {
772         C2F(mgetnc) (fd, (void*)&ln, &one, typ_char, err);
773         if (*err > 0)
774         {
775             goto ErrL;
776         }
777         *PosInRecord += 1;
778     }
779 
780     /*get the encoding options */
781     C2F(mgetnc) (fd, (void*)&OptionFlag, &one, typ_char, err);
782     if (*err > 0)
783     {
784         goto ErrL;
785     }
786     *PosInRecord += 1;
787 
788     UTFEncoding = (OptionFlag & 0x01) == 1;
789     extendedString = (OptionFlag & 0x04) != 0;
790     richString = (OptionFlag & 0x08) != 0;
791 
792     if (richString)   /*richString*/
793     {
794         C2F(mgetnc) (fd, (void*)&rt, &one, typ_short, err);
795         *PosInRecord += 2;
796         if (*err > 0)
797         {
798             goto ErrL;
799         }
800     }
801 
802     if (extendedString)  /* extendedString */
803     {
804         C2F(mgetnc) (fd, (void*)&sz, &one, typ_int, err);
805         if (*err > 0)
806         {
807             goto ErrL;
808         }
809         *PosInRecord += 4;
810     }
811 
812     /* number of bytes to be read */
813     BytesToBeRead = (UTFEncoding) ? ln * 2 : ln;
814 
815 
816     if ((*str = (char*) MALLOC((BytesToBeRead + 1) * sizeof(char))) == NULL)
817     {
818         goto ErrL;
819     }
820     /* read the bytes */
821 
822     if (!flag || (*PosInRecord + BytesToBeRead <= *RecordLen))
823     {
824         /* all bytes are in the same record */
825         C2F(mgetnc) (fd, (void*)*str, &BytesToBeRead, typ_char, err);
826         if (*err > 0)
827         {
828             goto ErrL;
829         }
830         *PosInRecord += (short)BytesToBeRead;
831     }
832     else  /* char stream contains at least one "continue" */
833     {
834         int bytesRead = *RecordLen - *PosInRecord; /* number of bytes before continue */
835         strindex = 0; /*current position in str*/
836         /* read bytes before the "continue"  */
837         /* according to documentation  bytesRead should be strictly positive */
838         C2F(mgetnc) (fd, (void*)(*str + strindex), &bytesRead, typ_char, err);
839         if (*err > 0)
840         {
841             goto ErrL;
842         }
843         strindex += bytesRead;
844         *PosInRecord += (short)bytesRead;
845         while (BytesToBeRead - bytesRead > 0)
846         {
847             /*"continue" tag assumed, verify */
848             C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
849             if ((*err > 0) || (Opcode != 60))
850             {
851                 goto ErrL;
852             }
853             C2F(mgetnc) (fd, RecordLen, &one, typ_ushort, err);
854             if (*err > 0)
855             {
856                 goto ErrL;
857             }
858             *PosInRecord = 0;
859             /* encoding option may change !!!! */
860             C2F(mgetnc) (fd, (void*)&OptionFlag, &one, typ_char, err);
861             if (*err > 0)
862             {
863                 goto ErrL;
864             }
865             *PosInRecord += 1;
866 
867             if ((!UTFEncoding && (OptionFlag == 0)) || (UTFEncoding && (OptionFlag != 0)))
868             {
869                 /*string encoding does not change */
870                 l1 = Min(BytesToBeRead - bytesRead, *RecordLen - *PosInRecord);
871                 C2F(mgetnc) (fd, (void*)(*str + strindex), &l1, typ_char, err);
872                 if (*err > 0)
873                 {
874                     goto ErrL;
875                 }
876                 bytesRead += l1;
877                 strindex += l1;
878                 *PosInRecord += (short)l1;
879             }
880             else if (UTFEncoding && (OptionFlag  == 0))
881             {
882                 /* character  encoding changes from twobytes to a single byte*/
883                 /* may this happen ???? */
884                 l1 = Min(BytesToBeRead - bytesRead, *RecordLen - *PosInRecord);
885                 for (j = 0; j < l1; j++)
886                 {
887                     C2F(mgetnc) (fd, (void*)(*str + strindex), &one, typ_char, err);
888                     if (*err > 0)
889                     {
890                         goto ErrL;
891                     }
892                     (*str)[strindex + 1] = '\0';
893                     strindex += 2;
894                     *PosInRecord += 2;
895                     UTFEncoding = 0;
896                 }
897             }
898             else
899             {
900                 /* character encoding changes from a single byte to two bytes */
901                 /* first, convert read characters to two bytes*/
902                 char *str1 = *str;
903                 strindex = 0;
904                 str = (char**) MALLOC((2 * BytesToBeRead + 1) * sizeof(char*));
905                 if (str == NULL)
906                 {
907                     goto ErrL;
908                 }
909                 for (j = 0; j < bytesRead; j++)
910                 {
911                     (*str)[strindex] = str1[j];
912                     (*str)[strindex + 1] = '\0';
913                     strindex += 2;
914                 }
915                 FREE(str1);
916                 BytesToBeRead = BytesToBeRead * 2;
917                 bytesRead = bytesRead * 2;
918                 /* read following two bytes characters */
919                 l1 = Min((BytesToBeRead - bytesRead) * 2, *RecordLen - *PosInRecord);
920                 C2F(mgetnc) (fd, (void*)(*str + strindex), &l1, typ_char, err);
921                 if (*err > 0)
922                 {
923                     goto ErrL;
924                 }
925                 bytesRead += l1;
926                 strindex += l1;
927                 *PosInRecord += (short)l1;
928                 UTFEncoding = 1;
929             }
930 
931         }
932 
933     } /*all character read */
934 
935     /* For extended strings, skip over the extended string data*/
936     /* may continuation records appear here? */
937     l1 = 4 * rt;
938     if (richString)
939     {
940         long long lll1 = (long long)l1;
941         *err = mseek(*fd, lll1, SEEK_CUR);
942         *PosInRecord += (short)l1;
943     }
944     if (extendedString)
945     {
946         long long llsz = (long long)sz;
947         *err = mseek(*fd, llsz, SEEK_CUR);
948         *PosInRecord += (short)sz;
949     }
950 
951     /* add string terminaison */
952     if (UTFEncoding)
953     {
954         /* Scilab currently do not support unicode, so we remove the second byte*/
955         strindex = 0;
956         for (j = 0; j < BytesToBeRead; j += 2)
957         {
958             (*str)[strindex] = (*str)[j];
959             strindex++;
960         }
961         BytesToBeRead = BytesToBeRead / 2;
962     }
963     (*str)[BytesToBeRead] = '\0';
964 
965 
966     return;
967 ErrL:
968     if (*err == 0)
969     {
970         FREE(*str);
971         *err = 3; /* malloc problem */
972     }
973     else
974     {
975         *err = 4;    /* read problem */
976     }
977 }
978 
getBoundsheets(int * fd,char *** Sheetnames,int ** Abspos,int * nsheets,long long * cur_pos,int * err)979 static void getBoundsheets(int * fd, char ***Sheetnames, int** Abspos, int *nsheets, long long *cur_pos, int *err)
980 {
981     /* the global workbook contains a sequence of boudsheets this procedure reads all
982     * the sequence and returns a vector o sheetnames, a vector of absolute sheet positions*/
983     int abspos; /* Absolute stream position of BoF*/
984     char visibility, sheettype; /*Visiblity , Sheet type*/
985     long long pos;
986     unsigned short Opcode;
987     unsigned short Len;
988     int one = 1;
989     int ns, i;
990 
991     *Sheetnames = (char **)NULL;
992     *Abspos = (int *)NULL;
993     *err = 0;
994 
995     /* memorize the first boundsheet beginning */
996     pos = *cur_pos;
997     /* Count number of boundsheets */
998     ns = 0;
999     while (1)
1000     {
1001         *err = mseek(*fd, *cur_pos, SEEK_SET);
1002         if (*err > 0)
1003         {
1004             goto ErrL;
1005         }
1006         C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
1007         if (*err > 0)
1008         {
1009             goto ErrL;
1010         }
1011         C2F(mgetnc) (fd, &Len, &one, typ_ushort, err);
1012         if (*err > 0)
1013         {
1014             goto ErrL;
1015         }
1016         if (Opcode == 133)
1017         {
1018             C2F(mgetnc) (fd, (void*)&abspos, &one, typ_int, err);
1019             if (*err > 0)
1020             {
1021                 goto ErrL;
1022             }
1023             C2F(mgetnc) (fd, (void*)&visibility, &one, typ_char, err);
1024             if (*err > 0)
1025             {
1026                 goto ErrL;
1027             }
1028             C2F(mgetnc) (fd, (void*)&sheettype, &one, typ_char, err);
1029             if (sheettype == 0) /* worksheet */
1030             {
1031                 ns++;
1032             }
1033             *cur_pos = *cur_pos + 4 + Len;
1034         }
1035         else
1036         {
1037             break;
1038         }
1039 
1040     }
1041 
1042     *nsheets = ns;
1043     /*alloc the Sheetnames ans Abspos arrays */
1044     if ( (*Sheetnames = (char **)MALLOC(ns * sizeof(char*))) == NULL)
1045     {
1046         goto ErrL;
1047     }
1048     if ( (*Abspos = (int *)MALLOC(ns * sizeof(int))) == NULL)
1049     {
1050         goto ErrL;
1051     }
1052 
1053     /* rescan boundsheet sequence to get the data */
1054     *cur_pos = pos;
1055     i = -1;
1056     while (1)
1057     {
1058         *err = mseek(*fd, *cur_pos, SEEK_SET);
1059         if (*err > 0)
1060         {
1061             goto ErrL;
1062         }
1063         C2F(mgetnc) (fd, &Opcode, &one, typ_ushort, err);
1064         C2F(mgetnc) (fd, &Len, &one, typ_ushort, err);
1065         if (Opcode == 133)
1066         {
1067             C2F(mgetnc) (fd, (void*)&abspos, &one, typ_int, err);
1068             if (*err > 0)
1069             {
1070                 goto ErrL;
1071             }
1072             C2F(mgetnc) (fd, (void*)&visibility, &one, typ_char, err);
1073             if (*err > 0)
1074             {
1075                 goto ErrL;
1076             }
1077             C2F(mgetnc) (fd, (void*)&sheettype, &one, typ_char, err);
1078             if (sheettype == 0) /* worksheet */
1079             {
1080                 short count = 0;
1081                 i++;
1082                 (*Abspos)[i] = abspos;
1083                 getString(fd, &count, (short *) &Len, 0, &((*Sheetnames)[i]), err);
1084                 if (*err > 0)
1085                 {
1086                     goto ErrL;
1087                 }
1088             }
1089             *cur_pos = *cur_pos + 4 + Len;
1090         }
1091         else
1092         {
1093             break;
1094         }
1095 
1096     }
1097     return;
1098 ErrL:
1099     if (*Sheetnames != NULL)
1100     {
1101         for (i = 0; i < ns; i++)
1102             if ( (*Sheetnames)[i] != NULL )
1103             {
1104                 FREE((*Sheetnames)[i]);
1105             }
1106         FREE(*Sheetnames);
1107     }
1108     FREE(*Abspos);
1109     if (*err == 0)
1110     {
1111         *err = 3;    /* malloc problem */
1112     }
1113     else
1114     {
1115         *err = 4;    /* read problem */
1116     }
1117 }
1118 
1119 /**
1120  ** Bruno : Defined but not used... so what !!!!!!!!!
1121  **
1122  static int get_oleheader(int *fd)
1123  {
1124  unsigned char MAGIC[8] = { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 };
1125  unsigned char header[512];
1126  int c,ierr;
1127 
1128  C2F(mgetnc) (fd, (void *)header,(c=512,&c), typ_uchar, &ierr);
1129  if (ierr !=0)  return 1;
1130  if (memcmp (header, MAGIC, sizeof (MAGIC)) != 0) return 1;
1131  return 0;
1132  }
1133 **/
1134