/*
    Convert a binary file into a HEX-file or back.
    Copyright (C) 2002  Wiesner Thomas^M
^M
    This program is free software; you can redistribute it and/or modify^M
    it under the terms of the GNU General Public License as published by^M
    the Free Software Foundation; either version 2 of the License, or^M
    (at your option) any later version.^M
^M
    This program is distributed in the hope that it will be useful,^M
    but WITHOUT ANY WARRANTY; without even the implied warranty of^M
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the^M
    GNU General Public License for more details.^M
^M
    You should have received a copy of the GNU General Public License^M
    along with this program; if not, write to the Free Software^M
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
    FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN^M
    OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES^M
    PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED^M
    OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF^M
    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS^M
    TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE^M
    PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,^M
    REPAIR OR CORRECTION.

*/

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define HDPL   38    // Hex digits per line

unsigned char digits[] = {'0', '1' ,'2' ,'3' ,'4' ,'5' ,'6' ,'7' ,'8' ,'9' ,'a' ,'b' ,'c' ,'d' ,'e' ,'f'};

void b2h(unsigned char c, char *str)
{
   unsigned char buf;

   buf = c;

   c <<= 4;
   c >>= 4;
   buf >>= 4;
   str[0] = digits[buf];
   str[1] = digits[c];
   str[2] = '\0';
}

unsigned char h2b(char *str)
{
   unsigned char byte;
   int i;

   for(i = 0; i < 16 && str[0] != digits[i]; i++)
      ;
   byte = i;
   byte <<= 4;
   for(i = 0; i < 16 && str[1] != digits[i]; i++)
      ;
   byte = byte + i;
   return byte;
}

int main(int argc, char *argv[])
{
   FILE *ifp;
   FILE *ofp;
   int c;
   int i;
   char num[3];

   if(argc != 4) {
      printf("Usage: %s infile outfile b2h/h2b\n", argv[0]);
      return -1;
   }

   if(strcmp(argv[3], "b2h") != 0 && strcmp(argv[3], "h2b") != 0) {
      printf("Third argument must be b2h (bin2hex) or h2b (hex2bin)\n");
      return -1;
   }

   if((ifp = fopen(argv[1], "rb")) == NULL) {
      printf("Unable to open input file\n");
      return -1;
   }

   if((ofp = fopen(argv[2], "wb")) == NULL) {
      printf("Unable to open output file\n");
      return -1;
   }


   if(strcmp(argv[3], "b2h") == 0) {
      printf("Bin to Hex conversion\n");
      i = 0;
      while((c = fgetc(ifp)) != EOF) {
         b2h(c, num);
         fputc(num[0], ofp);
         fputc(num[1], ofp);
         i++;
         if(i >= HDPL) {   // Be DOS compatible; Most unix editors can hadle it.
            fputc('\r', ofp);
            fputc('\n', ofp);
            i = 0;
         }
      }
   } else {
      printf("Hex to Bin conversion\n");
      while(1) {
         do {     // Get first hex digit
            c = fgetc(ifp);
         } while(!isxdigit(c) && c != EOF);
         if(c == EOF)
            break;
         num[0] = c;

         do {     // Get second hex digit
            c = fgetc(ifp);
         } while(!isxdigit(c) && c != EOF);
         if(c == EOF)
            break;
         num[1] = c;
         num[2] = '\0';
         i = h2b(num);
         fputc(i, ofp);
      }
   }

fclose(ifp);
fclose(ofp);
return 0;
}