//hex2bin.cpp Coded by x@rgs
#include<stdio.h>
#include<ctype.h>

//出力ファイル名用バッファ(省略された時のみ)
const int iFileNmaeBuffer=1024;

//fgets()用バッファ
const int iLineBuffer=1024;

long hex2dec(const int str){
	long lResult=0;
	char cChar=0;

	if('0'<=str&&str<='9'){
		lResult=str-'0';
	}else if('a'<=(cChar=tolower(str))&&cChar<='f'){
		lResult=cChar-'a'+10;
	}else{
		return 0;
	}

	return lResult;
}

int strlen(const char *str){
	int i=0;
	while(*str++)i++;
	return i;
}

int main(int argc,char *argv[]){
	FILE* fpIn;
	FILE* fpOut;

	if(argc==2||argc==3){
		if((fpIn=fopen(argv[1],"r"))!=NULL){
			char szOut[iFileNmaeBuffer]={0};
			char* pszOut;
			if(argc==2){
				//出力ファイル名が省略された時は〜.hexとして出力
				int i=strlen(argv[1]);
				if(i+1>iFileNmaeBuffer){
					//バッファが足りない時はa.hexとして出力
					szOut[0]='a';
					i=1;
				}else{
					pszOut=szOut;
					while((*(pszOut)++=*(argv[1])++));
				}
				szOut[i]='.';
				szOut[++i]='b';
				szOut[++i]='i';
				szOut[++i]='n';
			}

			if((fpOut=fopen((argc==2)?szOut:argv[2],"wb"))!=NULL){
				int i=0;
				char szLine[iLineBuffer];
				bool bInvalid=false;

				while(fgets(szLine,iLineBuffer,fpIn)!=NULL){
					i=0;
					while(szLine[i]!='\0'){
						//コメント関連の文字だった場合、次の行へ
						if(szLine[i]=='#'||szLine[i]=='/'||szLine[i]==';'){
							break;
						}else if(isspace(szLine[i])){
							//スペースやタブだった場合、次の文字へ
							i++;
						}else if(isxdigit(szLine[i])){
							if(!isxdigit(szLine[i+1])){
								//次の文字も16進数でなければ、無効なファイルとみなす
								bInvalid=true;
								break;
							}
							//変換
							int iTmp=hex2dec(szLine[i])*16;
							fputc(iTmp+hex2dec(szLine[++i]),fpOut);
							i++;
						}else{
							bInvalid=true;
							break;
						}
					}
					if(bInvalid)break;
				}
				fclose(fpOut);
				if(bInvalid){
					fprintf(stderr,"Invalid file\n");
					remove((argc==2)?szOut:argv[2]);
				}
			}else{
				fprintf(stderr,"Cannot open %s\n",(argc==2)?szOut:argv[2]);
			}
			fclose(fpIn);
		}else{
			fprintf(stderr,"Cannot open %s\n",argv[1]);
		}
	}else{
		fprintf(stderr,"Invalid argument\n");
	}
	return 0;
}
