PAPI  5.0.1.0
libbif.c
Go to the documentation of this file.
00001 /* 
00002  * Here is a very simple set of routines to write an Excel worksheet 
00003  * Microsoft BIFF format. The Excel version is set to 2.0 so that it 
00004  * will work with all versions of Excel.
00005  *
00006  * Author: Don Capps 
00007  */
00008 
00009 /* 
00010  * Note: rows and colums should not exceed 255 or this code will 
00011  * act poorly
00012  */
00013 
00014 #ifdef Windows
00015 #include <Windows.h>
00016 #endif
00017 #include <sys/types.h>
00018 #include <stdio.h>
00019 #include <sys/file.h>
00020 #if defined(__AIX__) || defined(__FreeBSD__) || defined(__DragonFly__)
00021 #include <fcntl.h>
00022 #else
00023 #include <sys/fcntl.h>
00024 #endif
00025 
00026 #if defined(OSV5) || defined(linux) || defined (__FreeBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__APPLE__) || defined(__DragonFly__)
00027 #include <string.h>
00028 #endif
00029 
00030 #if defined(linux) || defined(__DragonFly__) || defined(macosx)
00031 #include <unistd.h>
00032 #include <stdlib.h>
00033 #endif
00034 
00035 #if (defined(solaris) && defined( __LP64__ )) || defined(__s390x__) || defined(FreeBSD)
00036 /* If we are building for 64-bit Solaris, all functions that return pointers
00037  * must be declared before they are used; otherwise the compiler will assume
00038  * that they return ints and the top 32 bits of the pointer will be lost,
00039  * causing segmentation faults.  The following includes take care of this.
00040  * It should be safe to add these for all other OSs too, but we're only
00041  * doing it for Solaris now in case another OS turns out to be a special case.
00042  */
00043 #include <sys/stat.h>
00044 #include <fcntl.h>
00045 #include <unistd.h>
00046 #include <stdlib.h>
00047 #include <string.h>
00048 #endif
00049 /* Little Endian */
00050 #define ENDIAN_1  1
00051 /* Big Endian    */
00052 #define ENDIAN_2  2
00053 /* Middle Endian */
00054 #define ENDIAN_3  3
00055 /* Middle Endian */
00056 #define ENDIAN_4  4
00057 
00058 int junk, *junkp;
00059 
00060 
00061 #ifdef HAVE_ANSIC_C
00062 /************************************************************************/
00063 /* Here is the API... Enjoy                         */
00064 /************************************************************************/
00065 /* Create worksheet                             */
00066 int create_xls(char *);         
00067 /*    Args: Filename                            */
00068 /*                                      */
00069 /* Close worksheet                          */
00070 void close_xls(int);            
00071 /*   Args: file descriptor                      */
00072 /*                                      */
00073 /* Put a 16 bit integer in worksheet                    */
00074 void do_int(int,int,int,int);       
00075 /*    Args: file descriptor,                        */
00076 /*        value,                            */
00077 /*    row,                              */
00078 /*    column                            */
00079 
00080 /* Put a double in 8 byte float                     */
00081 void do_float(int,double,int,int);  
00082 /*    Args: file descriptor,                        */
00083 /*        value,                            */
00084 /*    row,                              */
00085 /*    column                            */
00086 /* Put a string in worksheet                        */
00087 void do_label(int,char *,int,int);  
00088 /*    Args: file descriptor,                        */
00089 /*        string,                           */
00090 /*    row,                              */
00091 /*    column                            */
00092 /************************************************************************/
00093 
00094 char libbif_version[] = "Libbif Version $Revision$";
00095 void do_eof(int );      /* Used internally */
00096 void do_header(int );       /* Used internally */
00097 int endian(void);
00098 #endif
00099 
00100 #define BOF 0x9
00101 #define INTEGER 0x2
00102 #define FLOAT 0x3
00103 #define LABEL 0x4
00104 #define EXCEL_VERS 0x2
00105 #define WORKSHEET 0x10
00106 
00107 struct bof_record{      /* Beginning of file */
00108     char hi_opcode;
00109     char lo_opcode;
00110     char hi_length;
00111     char lo_length;
00112     char hi_version;    /* Excel version */
00113     char lo_version;
00114     char hi_filetype;
00115     char lo_filetype;
00116     };
00117 struct int_record {
00118     char hi_opcode;     /* Type 2 of record */
00119     char lo_opcode;
00120     char hi_length;
00121     char lo_length;
00122     char hi_row;
00123     char lo_row;
00124     char hi_column;
00125     char lo_column;
00126     char rgbhi;
00127     char rgbmed;
00128     char rgblo;
00129     char hi_data;
00130     char lo_data;
00131     };
00132 struct label_record {
00133     char hi_opcode;     /* Type 4 of record */
00134     char lo_opcode;
00135     char hi_length;
00136     char lo_length;
00137     char hi_row;
00138     char lo_row;
00139     char hi_column;
00140     char lo_column;
00141     char rgbhi;
00142     char rgbmed;
00143     char rgblo;
00144     char string_length;
00145     char str_array[256];
00146     };
00147 struct float_record {       /* Type 3 record */
00148     char hi_opcode;
00149     char lo_opcode;
00150     char hi_length;
00151     char lo_length;
00152     char hi_row;
00153     char lo_row;
00154     char hi_column;
00155     char lo_column;
00156     char rgbhi;
00157     char rgbmed;
00158     char rgblo;
00159     double data;
00160     };
00161 /*
00162  * Write the EOF and close the file 
00163  */
00164 #ifdef HAVE_ANSIC_C
00165 void
00166 close_xls(int fd)
00167 {
00168 #else
00169 close_xls(fd)
00170 int fd;
00171 {
00172 #endif
00173     do_eof(fd);
00174     close(fd);
00175 }
00176 
00177 /*
00178  * Create xls worksheet. Create file and put the BOF record in it.
00179  */
00180 #ifdef HAVE_ANSIC_C
00181 int
00182 create_xls(char *name)
00183 {
00184 #else
00185 create_xls(name)
00186 char *name;
00187 {
00188 #endif
00189     int fd;
00190     unlink(name);
00191 #ifdef Windows
00192     fd=open(name,O_BINARY|O_CREAT|O_RDWR,0666);
00193 #else
00194     fd=open(name,O_CREAT|O_RDWR,0666);
00195 #endif
00196     if(fd<0)
00197     {
00198         printf("Error opening file %s\n",name);
00199         exit(-1);
00200     }
00201     do_header(fd);
00202     return(fd);
00203 }
00204     
00205 #ifdef HAVE_ANSIC_C
00206 void
00207 do_header(int fd) /* Stick the BOF at the beginning of the file */
00208 {
00209 #else
00210 do_header(fd) 
00211 int fd;
00212 {
00213 #endif
00214     struct bof_record bof;
00215     bof.hi_opcode=BOF;
00216     bof.lo_opcode = 0x0;
00217     bof.hi_length=0x4;
00218     bof.lo_length=0x0;
00219     bof.hi_version=EXCEL_VERS;
00220     bof.lo_version=0x0;
00221     bof.hi_filetype=WORKSHEET;
00222     bof.lo_filetype=0x0;
00223     junk=write(fd,&bof,sizeof(struct bof_record));
00224 }
00225 
00226 /*
00227  * Put an integer (16 bit) in the worksheet 
00228  */
00229 #ifdef HAVE_ANSIC_C
00230 void
00231 do_int(int fd,int val, int row, int column)
00232 {
00233 #else
00234 do_int(fd,val,row,column)
00235 int fd,val,row,column;
00236 {
00237 #endif
00238     struct int_record intrec;
00239     short s_row,s_column;
00240     s_row=(short)row;
00241     s_column=(short)column;
00242         intrec.hi_opcode=INTEGER;
00243         intrec.lo_opcode=0x00;
00244         intrec.hi_length=0x09;
00245         intrec.lo_length=0x00;
00246         intrec.rgbhi=0x0;
00247         intrec.rgbmed=0x0;
00248         intrec.rgblo=0x0;
00249         intrec.hi_row=(char)s_row&0xff;
00250         intrec.lo_row=(char)(s_row>>8)&0xff;
00251         intrec.hi_column=(char)(s_column&0xff);
00252         intrec.lo_column=(char)(s_column>>8)&0xff;
00253         intrec.hi_data=(val & 0xff);
00254         intrec.lo_data=(val & 0xff00)>>8;
00255     junk=write(fd,&intrec,13);
00256 }
00257 
00258 /* Note: This routine converts Big Endian to Little Endian 
00259  * and writes the record out.
00260  */
00261 
00262 /* 
00263  * Put a double in the worksheet as 8 byte float in IEEE format.
00264  */
00265 #ifdef HAVE_ANSIC_C
00266 void
00267 do_float(int fd, double value, int row, int column)
00268 {
00269 #else
00270 do_float(fd, value, row, column)
00271 int fd;
00272 double value;
00273 int row,column;
00274 {
00275 #endif
00276     struct float_record floatrec;
00277     short s_row,s_column;
00278     unsigned char *sptr,*dptr;
00279     s_row=(short)row;
00280     s_column=(short)column;
00281         floatrec.hi_opcode=FLOAT;
00282         floatrec.lo_opcode=0x00;
00283         floatrec.hi_length=0xf;
00284         floatrec.lo_length=0x00;
00285         floatrec.rgbhi=0x0;
00286         floatrec.rgbmed=0x0;
00287         floatrec.rgblo=0x0;
00288         floatrec.hi_row=(char)(s_row&0xff);
00289         floatrec.lo_row=(char)((s_row>>8)&0xff);
00290         floatrec.hi_column=(char)(s_column&0xff);
00291         floatrec.lo_column=(char)((s_column>>8)&0xff);
00292     sptr =(unsigned char *) &value;
00293     dptr =(unsigned char *) &floatrec.data;
00294 
00295     if(endian()==ENDIAN_2) /* Big Endian */
00296     {
00297        dptr[0]=sptr[7]; /* Convert to Little Endian */
00298        dptr[1]=sptr[6];
00299        dptr[2]=sptr[5];
00300        dptr[3]=sptr[4];
00301        dptr[4]=sptr[3];
00302        dptr[5]=sptr[2];
00303        dptr[6]=sptr[1];
00304        dptr[7]=sptr[0];
00305     }
00306     if(endian()==ENDIAN_3)  /* Middle Endian */
00307     {
00308        dptr[0]=sptr[4]; /* 16 bit swapped ARM */
00309        dptr[1]=sptr[5];
00310        dptr[2]=sptr[6];
00311        dptr[3]=sptr[7];
00312        dptr[4]=sptr[0];
00313        dptr[5]=sptr[1];
00314        dptr[6]=sptr[2];
00315        dptr[7]=sptr[3];
00316     }
00317 
00318     if(endian()==ENDIAN_1) /* Little Endian */
00319     {
00320        dptr[0]=sptr[0]; /* Do not convert to Little Endian */
00321        dptr[1]=sptr[1];
00322        dptr[2]=sptr[2];
00323        dptr[3]=sptr[3];
00324        dptr[4]=sptr[4];
00325        dptr[5]=sptr[5];
00326        dptr[6]=sptr[6];
00327        dptr[7]=sptr[7];
00328     }
00329     if(endian()==-1) /* Unsupported architecture */
00330     {
00331        dptr[0]=0;
00332        dptr[1]=0;
00333        dptr[2]=0;
00334        dptr[3]=0;
00335        dptr[4]=0;
00336        dptr[5]=0;
00337        dptr[6]=0;
00338        dptr[7]=0;
00339        printf("Excel output not supported on this architecture.\n");
00340     }
00341     junk=write(fd,&floatrec,11); /* Don't write floatrec. Padding problems */
00342     junk=write(fd,&floatrec.data,8); /* Write value seperately */
00343 }
00344 
00345 /*
00346  * Put a string as a label in the worksheet.
00347  */
00348 #ifdef HAVE_ANSIC_C
00349 void
00350 do_label(int fd, char *string, int row, int column)
00351 {
00352 #else
00353 do_label(fd, string, row, column)
00354 int fd;
00355 char *string;
00356 int row,column;
00357 {
00358 #endif
00359     struct label_record labelrec;
00360     short s_row,s_column;
00361     int i;
00362     for(i=0;i<255;i++)
00363         labelrec.str_array[i]=0;
00364     s_row=(short)row;
00365     s_column=(short)column;
00366     i=strlen(string);
00367         labelrec.hi_opcode=LABEL;
00368         labelrec.lo_opcode=0x00;
00369         labelrec.hi_length=0x08; /* 264 total bytes */
00370         labelrec.lo_length=0x01;
00371         labelrec.rgblo=0x0;
00372         labelrec.rgbmed=0x0;
00373         labelrec.rgbhi=0x0;
00374         labelrec.hi_row=(char)(s_row&0xff);
00375         labelrec.lo_row=(char)((s_row>>8)&0xff);
00376         labelrec.hi_column=(char)(s_column&0xff);
00377         labelrec.lo_column=(char)((s_column>>8)&0xff);
00378     labelrec.string_length=i;
00379     if(i > 255) /* If too long then terminate it early */
00380         string[254]=0;
00381     i=strlen(string);
00382     strcpy(labelrec.str_array,string);
00383 
00384     junk=write(fd,&labelrec,sizeof(struct label_record));
00385 
00386 }
00387 
00388 /* 
00389  * Write the EOF in the file 
00390  */
00391 #ifdef HAVE_ANSIC_C
00392 void
00393 do_eof(int fd) 
00394 {
00395 #else
00396 do_eof(fd) 
00397 int fd;
00398 {
00399 #endif
00400     char buf[]={0x0a,0x00,0x00,0x00};
00401     junk=write(fd,buf,4);
00402 }
00403     
00404 /* 
00405  * Routine to determine the Endian-ness of the system. This
00406  * is needed for Iozone to convert doubles (floats) into
00407  * Little-endian format. This is needed for Excel to be 
00408  * able to interpret the file 
00409  */
00410 int
00411 endian(void)
00412 {
00413     long long foo = 0x0102030405060708LL;
00414     long foo1 = 0x012345678;
00415     unsigned char *c,c1,c2,c3,c4,c5,c6,c7,c8;
00416     c=(unsigned char *)&foo;
00417     c1=*c++;
00418     c2=*c++;
00419     c3=*c++;
00420     c4=*c++;
00421     c5=*c++;
00422     c6=*c++;
00423     c7=*c++;
00424     c8=*c;
00425 
00426     /*--------------------------------------------------------------*/
00427     /* printf("%x %x %x %x %x %x %x %x\n",c1,c2,c3,c4,c5,c6,c7,c8); */
00428     /*--------------------------------------------------------------*/
00429 
00430     /* Little Endian format ? ( Intel ) */
00431     if( (c1==0x08) && (c2==0x07) && (c3==0x06) && (c4==0x05) &&
00432         (c5==0x04) && (c6==0x03) && (c7==0x02) && (c8==0x01) )
00433         return(ENDIAN_1);
00434     /* Big Endian format ?    ( Sparc, Risc... */
00435     if( (c1==0x01) && (c2==0x02) && (c3==0x03) && (c4==0x04) &&
00436         (c5==0x05) && (c6==0x06) && (c7==0x07) && (c8==0x08) )
00437         return(ENDIAN_2);
00438     /* Middle Endian format ? ( ARM ... ) */
00439     if( (c1==0x04) && (c2==0x03) && (c3==0x02) && (c4==0x01) &&
00440         (c5==0x08) && (c6==0x07) && (c7==0x06) && (c8==0x05) )
00441         return(ENDIAN_3);
00442     c=(unsigned char *)&foo1;
00443     c1=*c++;
00444     c2=*c++;
00445     c3=*c++;
00446     c4=*c++;
00447     /* Another middle endian format ? ( PDP-11 ... ) */
00448     if( (c1==0x34) && (c2==0x12) && (c3==0x78) && (c4==0x56))
00449         return(ENDIAN_4);
00450 
00451     return(-1);
00452 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines