#include #include #include #include #define MAXLINEWIDTH (79) void usage(){ fprintf(stderr, "Usage: bin2c [inputfile] [outputfile]\n" "\n" "Converts a binary file to a C string that denotes the same binary contents, but\n" "is parseable by a C compiler.\n" "Default values for the arguments are stdin and stdout; also '-' indicates the\n" "standard stream.\n"); } // Returns serialised string length // Keeps state on the previous few characters to aid compression and prevent // trigraphs int serialisechar(char *dst,unsigned char c){ static bool lastwasoctal=false; static unsigned char prevc; switch(c){ case '\a': lastwasoctal=false; prevc=c; dst[0]='\\'; dst[1]='a'; return 2; case '\b': lastwasoctal=false; prevc=c; dst[0]='\\'; dst[1]='b'; return 2; case '\f': lastwasoctal=false; prevc=c; dst[0]='\\'; dst[1]='f'; return 2; case '\n': lastwasoctal=false; prevc=c; dst[0]='\\'; dst[1]='n'; return 2; case '\r': lastwasoctal=false; prevc=c; dst[0]='\\'; dst[1]='r'; return 2; case '\t': lastwasoctal=false; prevc=c; dst[0]='\\'; dst[1]='t'; return 2; case '\v': lastwasoctal=false; prevc=c; dst[0]='\\'; dst[1]='v'; return 2; case '"': lastwasoctal=false; prevc=c; dst[0]='\\'; dst[1]='"'; return 2; case '\\': lastwasoctal=false; prevc=c; dst[0]='\\'; dst[1]='\\'; return 2; default: if(c<32||c>=127){ lastwasoctal=true; prevc=c; return sprintf(dst,"\\%o",(int)c); } else if(isdigit(c)&&lastwasoctal&&prevc<'\100'){ prevc=c; return sprintf(dst,"\\%o",(int)c); } else if(c=='?'&&prevc=='?'){ lastwasoctal=false; dst[0]='\\'; dst[1]='?'; return 2; } else { lastwasoctal=false; dst[0]=c; prevc=c; return 1; } } } // Returns new xposition int convertbuffer(FILE *output,const char *buffer,int length,int xposition){ char cbuf[8]; for(int i=0;iMAXLINEWIDTH){ fputc('"',output); fputc('\n',output); fputc('"',output); xposition=1; } fwrite(cbuf,1,clen,output); xposition+=clen; } return xposition; } void bin2c(FILE *input,FILE *output){ fputc('"',output); char buffer[1024]; int xposition=1; while(true){ size_t nread=fread(buffer,1,sizeof(buffer),input); if(nread==0){ break; } xposition=convertbuffer(output,buffer,nread,xposition); if(feof(input)||ferror(input)){ break; } } fputc('"',output); fputc('\n',output); } int main(int argc,char **argv){ if(argc==1){ bin2c(stdin,stdout); } else if(argc==2){ if(strcmp(argv[1],"-h")==0||strcmp(argv[1],"--help")==0){ usage(); } else if(strcmp(argv[1],"-")==0){ bin2c(stdin,stdout); } else { FILE *f=fopen(argv[1],"rb"); if(!f){ fprintf(stderr,"Could not open file '%s'\n",argv[1]); return 1; } bin2c(f,stdout); fclose(f); } } else if(argc==3){ FILE *fin,*fout; if(strcmp(argv[1],"-")==0){ fin=stdin; } else { fin=fopen(argv[1],"rb"); if(!fin){ fprintf(stderr,"Could not open file '%s'\n",argv[1]); return 1; } } if(strcmp(argv[2],"-")==0){ fout=stdout; } else { fout=fopen(argv[2],"wb"); if(!fout){ fprintf(stderr,"Could not open file '%s'\n",argv[2]); return 1; } } bin2c(fin,fout); fclose(fin); fclose(fout); } else { usage(); return 1; } }