summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2016-12-21 11:58:19 +0100
committertomsmeding <tom.smeding@gmail.com>2016-12-21 11:58:19 +0100
commit433db0b34b386977ab50234d3b90833d981f6f04 (patch)
tree74ac0e8509b9cfe77b4fefdeb260cfd50665740c
parentf017ddf090f9602e750c7db22d034b4a707fff1f (diff)
Add c2bin
-rw-r--r--.gitignore1
-rw-r--r--Makefile2
-rw-r--r--c2bin.c164
3 files changed, 166 insertions, 1 deletions
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 <ctype.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+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;
+ }
+}