From 433db0b34b386977ab50234d3b90833d981f6f04 Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Wed, 21 Dec 2016 11:58:19 +0100 Subject: Add c2bin --- .gitignore | 1 + Makefile | 2 +- c2bin.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 c2bin.c diff --git a/.gitignore b/.gitignore index 6793ace..dd20adc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ bin2c +c2bin *.o *.dSYM diff --git a/Makefile b/Makefile index 6e84e3d..59d835c 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ ifneq ($(DEBUG),) else CFLAGS += -O2 endif -BIN = bin2c +BIN = bin2c c2bin .PHONY: all clean remake diff --git a/c2bin.c b/c2bin.c new file mode 100644 index 0000000..b15ee88 --- /dev/null +++ b/c2bin.c @@ -0,0 +1,164 @@ +#include +#include +#include +#include +#include + +void usage(){ + fprintf(stderr, + "Usage: c2bin [inputfile] [outputfile]\n" + "\n" + "Converts a C string to its parsed contents. The inverse of bin2c.\n" + "Default values for the arguments are stdin and stdout; also '-' indicates the\n" + "standard stream.\n"); +} + +int unhex(int c){ + if(c>='0'&&c<='9'){ + return c-'0'; + } else if(c>='a'&&c<='f'){ + return c-'a'+10; + } else if(c>='A'&&c<='F'){ + return c-'A'+10; + } else { + return -1; + } +} + +void c2bin(FILE *input,FILE *output){ + bool stringmode=false; + int c; + while((c=fgetc(input))!=EOF){ + if(c=='"'){ + stringmode=!stringmode; + } else if(!stringmode){ + if(!isspace(c)){ + fprintf(stderr,"Characters outside string\n"); + exit(1); + } + } else if(c=='\n'){ + fprintf(stderr,"Invalid newline in string\n"); + exit(1); + } else if(c!='\\'){ + fputc(c,output); + } else { + c=fgetc(input); + if(c==EOF){ + fprintf(stderr,"Invalid backslash at end of input\n"); + exit(1); + } else if(c=='\n'){ + continue; + } else if(c!='x'&&!isdigit(c)){ + switch(c){ + case 'a': fputc('\a',output); break; + case 'b': fputc('\b',output); break; + case 'f': fputc('\f',output); break; + case 'n': fputc('\n',output); break; + case 'r': fputc('\r',output); break; + case 't': fputc('\t',output); break; + case 'v': fputc('\v',output); break; + default: fputc(c,output); break; + } + } else if(c=='x'){ + int c1=fgetc(input); + int c2=fgetc(input); + if(c1==-1||c2==-1){ + fprintf(stderr,"Invalid end of input\n"); + exit(1); + } + c1=unhex(c1); + c2=unhex(c2); + if(c1==-1){ + fprintf(stderr,"Invalid hexadecimal escape\n"); + exit(1); + } + if(c2==-1){ + fputc(c1,output); + } else { + c=fgetc(input); + if(c==-1){ + fprintf(stderr,"Invalid end of input\n"); + exit(1); + } + if(unhex(c)!=-1){ + fprintf(stderr,"Invalid wide hexadecimal escape\n"); + exit(1); + } + ungetc(c,input); + + fputc(16*c1+c2,output); + } + } else { + ungetc(c,input); + int res=0,i; + for(i=0;i<3;i++){ + c=fgetc(input); + if(c==EOF){ + fprintf(stderr,"Invalid end of input\n"); + exit(1); + } + if(c<'0'||c>='8'){ + ungetc(c,input); + break; + } + res=8*res+c-'0'; + } + if(i==0){ + fprintf(stderr,"Invalid octal escape\n"); + exit(1); + } + fputc(res,output); + } + } + fflush(output); + } +} + +int main(int argc,char **argv){ + if(argc==1){ + c2bin(stdin,stdout); + } else if(argc==2){ + if(strcmp(argv[1],"-h")==0||strcmp(argv[1],"--help")==0){ + usage(); + } else if(strcmp(argv[1],"-")==0){ + c2bin(stdin,stdout); + } else { + FILE *f=fopen(argv[1],"rb"); + if(!f){ + fprintf(stderr,"Could not open file '%s'\n",argv[1]); + return 1; + } + c2bin(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],"rb"); + if(!fout){ + fprintf(stderr,"Could not open file '%s'\n",argv[2]); + return 1; + } + } + + c2bin(fin,fout); + + fclose(fin); + fclose(fout); + } else { + usage(); + return 1; + } +} -- cgit v1.2.3-70-g09d2