📄 libbif.c
字号:
/* * Here is a very simple set of routines to write an Excel worksheet * Microsoft BIFF format. The Excel version is set to 2.0 so that it * will work with all versions of Excel. * * Author: Don Capps *//* * Note: rows and colums should not exceed 255 or this code will * act poorly */#include <sys/types.h>#include <stdio.h>#include <sys/file.h>#if defined(__AIX__) || defined(__FreeBSD__) || defined(__DragonFly__)#include <fcntl.h>#else#include <sys/fcntl.h>#endif#if defined(OSV5) || defined(linux) || defined (__FreeBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__APPLE__) || defined(__DragonFly__)#include <string.h>#endif#if defined(linux) || defined(__DragonFly__) || defined(macosx)#include <unistd.h>#include <stdlib.h>#endif#if ((defined(solaris) && defined( __LP64__ )) || defined(__s390x__))/* If we are building for 64-bit Solaris, all functions that return pointers * must be declared before they are used; otherwise the compiler will assume * that they return ints and the top 32 bits of the pointer will be lost, * causing segmentation faults. The following includes take care of this. * It should be safe to add these for all other OSs too, but we're only * doing it for Solaris now in case another OS turns out to be a special case. */#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#endif/* Little Endian */#define ENDIAN_1 1/* Big Endian */#define ENDIAN_2 2/* Middle Endian */#define ENDIAN_3 3/* Middle Endian */#define ENDIAN_4 4#ifdef HAVE_ANSIC_C/************************************************************************//* Here is the API... Enjoy *//************************************************************************//* Create worksheet */int create_xls(char *); /* Args: Filename *//* *//* Close worksheet */void close_xls(int); /* Args: file descriptor *//* *//* Put a 16 bit integer in worksheet */void do_int(int,int,int,int); /* Args: file descriptor, *//* value, *//* row, *//* column *//* Put a double in 8 byte float */void do_float(int,double,int,int); /* Args: file descriptor, *//* value, *//* row, *//* column *//* Put a string in worksheet */void do_label(int,char *,int,int); /* Args: file descriptor, *//* string, *//* row, *//* column *//************************************************************************/char libbif_version[] = "Libbif Version $Revision: 3.22 $";void do_eof(int ); /* Used internally */void do_header(int ); /* Used internally */int endian(void);#endif#define BOF 0x9#define INTEGER 0x2#define FLOAT 0x3#define LABEL 0x4#define EXCEL_VERS 0x2#define WORKSHEET 0x10struct bof_record{ /* Beginning of file */ char hi_opcode; char lo_opcode; char hi_length; char lo_length; char hi_version; /* Excel version */ char lo_version; char hi_filetype; char lo_filetype; };struct int_record { char hi_opcode; /* Type 2 of record */ char lo_opcode; char hi_length; char lo_length; char hi_row; char lo_row; char hi_column; char lo_column; char rgbhi; char rgbmed; char rgblo; char hi_data; char lo_data; };struct label_record { char hi_opcode; /* Type 4 of record */ char lo_opcode; char hi_length; char lo_length; char hi_row; char lo_row; char hi_column; char lo_column; char rgbhi; char rgbmed; char rgblo; char string_length; char str_array[256]; };struct float_record { /* Type 3 record */ char hi_opcode; char lo_opcode; char hi_length; char lo_length; char hi_row; char lo_row; char hi_column; char lo_column; char rgbhi; char rgbmed; char rgblo; double data; };/* * Write the EOF and close the file */#ifdef HAVE_ANSIC_Cvoidclose_xls(int fd){#elseclose_xls(fd)int fd;{#endif do_eof(fd); close(fd);}/* * Create xls worksheet. Create file and put the BOF record in it. */#ifdef HAVE_ANSIC_Cintcreate_xls(char *name){#elsecreate_xls(name)char *name;{#endif int fd; unlink(name);#ifdef Windows fd=open(name,O_BINARY|O_CREAT|O_RDWR,0666);#else fd=open(name,O_CREAT|O_RDWR,0666);#endif if(fd<0) { printf("Error opening file %s\n",name); exit(-1); } do_header(fd); return(fd);} #ifdef HAVE_ANSIC_Cvoiddo_header(int fd) /* Stick the BOF at the beginning of the file */{#elsedo_header(fd) int fd;{#endif struct bof_record bof; bof.hi_opcode=BOF; bof.lo_opcode = 0x0; bof.hi_length=0x4; bof.lo_length=0x0; bof.hi_version=EXCEL_VERS; bof.lo_version=0x0; bof.hi_filetype=WORKSHEET; bof.lo_filetype=0x0; write(fd,&bof,sizeof(struct bof_record));}/* * Put an integer (16 bit) in the worksheet */#ifdef HAVE_ANSIC_Cvoiddo_int(int fd,int val, int row, int column){#elsedo_int(fd,val,row,column)int fd,val,row,column;{#endif struct int_record intrec; short s_row,s_column; s_row=(short)row; s_column=(short)column; intrec.hi_opcode=INTEGER; intrec.lo_opcode=0x00; intrec.hi_length=0x09; intrec.lo_length=0x00; intrec.rgbhi=0x0; intrec.rgbmed=0x0; intrec.rgblo=0x0; intrec.hi_row=(char)s_row&0xff; intrec.lo_row=(char)(s_row>>8)&0xff; intrec.hi_column=(char)(s_column&0xff); intrec.lo_column=(char)(s_column>>8)&0xff; intrec.hi_data=(val & 0xff); intrec.lo_data=(val & 0xff00)>>8; write(fd,&intrec,13);}/* Note: This routine converts Big Endian to Little Endian * and writes the record out. *//* * Put a double in the worksheet as 8 byte float in IEEE format. */#ifdef HAVE_ANSIC_Cvoiddo_float(int fd, double value, int row, int column){#elsedo_float(fd, value, row, column)int fd;double value;int row,column;{#endif struct float_record floatrec; short s_row,s_column; unsigned char *sptr,*dptr; s_row=(short)row; s_column=(short)column; floatrec.hi_opcode=FLOAT; floatrec.lo_opcode=0x00; floatrec.hi_length=0xf; floatrec.lo_length=0x00; floatrec.rgbhi=0x0; floatrec.rgbmed=0x0; floatrec.rgblo=0x0; floatrec.hi_row=(char)(s_row&0xff); floatrec.lo_row=(char)((s_row>>8)&0xff); floatrec.hi_column=(char)(s_column&0xff); floatrec.lo_column=(char)((s_column>>8)&0xff); sptr =(unsigned char *) &value; dptr =(unsigned char *) &floatrec.data; if(endian()==ENDIAN_2) /* Big Endian */ { dptr[0]=sptr[7]; /* Convert to Little Endian */ dptr[1]=sptr[6]; dptr[2]=sptr[5]; dptr[3]=sptr[4]; dptr[4]=sptr[3]; dptr[5]=sptr[2]; dptr[6]=sptr[1]; dptr[7]=sptr[0]; } if(endian()==ENDIAN_3) /* Middle Endian */ { dptr[0]=sptr[4]; /* 16 bit swapped ARM */ dptr[1]=sptr[5]; dptr[2]=sptr[6]; dptr[3]=sptr[7]; dptr[4]=sptr[0]; dptr[5]=sptr[1]; dptr[6]=sptr[2]; dptr[7]=sptr[3]; } if(endian()==ENDIAN_1) /* Little Endian */ { dptr[0]=sptr[0]; /* Do not convert to Little Endian */ dptr[1]=sptr[1]; dptr[2]=sptr[2]; dptr[3]=sptr[3]; dptr[4]=sptr[4]; dptr[5]=sptr[5]; dptr[6]=sptr[6]; dptr[7]=sptr[7]; } if(endian()==-1) /* Unsupported architecture */ { dptr[0]=0; dptr[1]=0; dptr[2]=0; dptr[3]=0; dptr[4]=0; dptr[5]=0; dptr[6]=0; dptr[7]=0; printf("Excel output not supported on this architecture.\n"); } write(fd,&floatrec,11); /* Don't write floatrec. Padding problems */ write(fd,&floatrec.data,8); /* Write value seperately */}/* * Put a string as a label in the worksheet. */#ifdef HAVE_ANSIC_Cvoiddo_label(int fd, char *string, int row, int column){#elsedo_label(fd, string, row, column)int fd;char *string;int row,column;{#endif struct label_record labelrec; short s_row,s_column; int i; for(i=0;i<255;i++) labelrec.str_array[i]=0; s_row=(short)row; s_column=(short)column; i=strlen(string); labelrec.hi_opcode=LABEL; labelrec.lo_opcode=0x00; labelrec.hi_length=0x08; /* 264 total bytes */ labelrec.lo_length=0x01; labelrec.rgblo=0x0; labelrec.rgbmed=0x0; labelrec.rgbhi=0x0; labelrec.hi_row=(char)(s_row&0xff); labelrec.lo_row=(char)((s_row>>8)&0xff); labelrec.hi_column=(char)(s_column&0xff); labelrec.lo_column=(char)((s_column>>8)&0xff); labelrec.string_length=i; if(i > 255) /* If too long then terminate it early */ string[254]=0; i=strlen(string); strcpy(labelrec.str_array,string); write(fd,&labelrec,sizeof(struct label_record));}/* * Write the EOF in the file */#ifdef HAVE_ANSIC_Cvoiddo_eof(int fd) {#elsedo_eof(fd) int fd;{#endif char buf[]={0x0a,0x00,0x00,0x00}; write(fd,buf,4);} /* * Routine to determine the Endian-ness of the system. This * is needed for Iozone to convert doubles (floats) into * Little-endian format. This is needed for Excel to be * able to interpret the file */intendian(void){ long long foo = 0x0102030405060708LL; long foo1 = 0x012345678; unsigned char *c,c1,c2,c3,c4,c5,c6,c7,c8; c=(unsigned char *)&foo; c1=*c++; c2=*c++; c3=*c++; c4=*c++; c5=*c++; c6=*c++; c7=*c++; c8=*c; /*--------------------------------------------------------------*/ /* printf("%x %x %x %x %x %x %x %x\n",c1,c2,c3,c4,c5,c6,c7,c8); */ /*--------------------------------------------------------------*/ /* Little Endian format ? ( Intel ) */ if( (c1==0x08) && (c2==0x07) && (c3==0x06) && (c4==0x05) && (c5==0x04) && (c6==0x03) && (c7==0x02) && (c8==0x01) ) return(ENDIAN_1); /* Big Endian format ? ( Sparc, Risc... */ if( (c1==0x01) && (c2==0x02) && (c3==0x03) && (c4==0x04) && (c5==0x05) && (c6==0x06) && (c7==0x07) && (c8==0x08) ) return(ENDIAN_2); /* Middle Endian format ? ( ARM ... ) */ if( (c1==0x04) && (c2==0x03) && (c3==0x02) && (c4==0x01) && (c5==0x08) && (c6==0x07) && (c7==0x06) && (c8==0x05) ) return(ENDIAN_3); c=(unsigned char *)&foo1; c1=*c++; c2=*c++; c3=*c++; c4=*c++; /* Another middle endian format ? ( PDP-11 ... ) */ if( (c1==0x34) && (c2==0x12) && (c3==0x78) && (c4==0x56)) return(ENDIAN_4); return(-1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -