|
PAPI
5.0.1.0
|
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 }