diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | c2bin.c | 164 |
3 files changed, 166 insertions, 1 deletions
@@ -1,3 +1,4 @@ bin2c +c2bin *.o *.dSYM @@ -5,7 +5,7 @@ ifneq ($(DEBUG),) else CFLAGS += -O2 endif -BIN = bin2c +BIN = bin2c c2bin .PHONY: all clean remake @@ -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; + } +} |