#include <stdio.h>

unsigned char hex2bin(unsigned char c)
{
  if (c >= '0' && c <= '9') return(c - '0');
  else if (c >= 'A' && c <= 'F') return(c + 10 - 'A');
  else if (c >= 'a' && c <= 'f') return(c + 10 - 'a');
  else return(0);
}

unsigned char hexhex2bin(unsigned char *buf)
{
  return(hex2bin(*buf) << 4 | hex2bin(*(buf+1)));
}

void print_hexline(unsigned char hlen, unsigned int haddr, unsigned int htype, unsigned char *rbuf){
  unsigned int s0, i;
  s0 = hlen + (haddr >> 8) + (haddr & 0xff) + htype;
  printf(":%02X%04X%02X", hlen, haddr, htype);
  for (i = 0; i < hlen; i++){
    printf("%02X", rbuf[i]);
    s0 += rbuf[i];
  }
  printf("%02X\r\n", (~s0 + 1) & 0xff);
}

unsigned char bin2hex(unsigned char d)
{
  if (d <= 9) return('0'+d);
  else if (d < 16) return('A'-10+d);
  else return('-');
}

main(int ac, char **av)
{
  char buf[1024];
  unsigned int s, s0;
  int i, l;
  char fin;
  unsigned char d;
  unsigned int sa;
  FILE *fp;
  unsigned int hlen, haddr, htype, oaddr;
  unsigned char rbuf[1024];
  int c0;

  sa = 0;
  if (ac > 2){
    if (strlen(av[1]) != 4){
      fprintf(stderr, "Offset address must be 4 digit hexadecimal.\n");
      exit(1);
    }
    sa = hex2bin(av[1][0]) << 12 | hex2bin(av[1][1]) << 8 | hex2bin(av[1][2]) << 4 | hex2bin(av[1][3]);
    if ((fp = fopen(av[2], "rb")) == NULL){
      fprintf(stderr, "can't open %s\n", av[2]);
      exit(1);
    }
  }
  else{
    sa = -1;
  }

  s = 0;
  fin = 0;
  while(fgets(buf, 1023, stdin) != NULL){
    hlen = hexhex2bin(buf+1);
    haddr = hexhex2bin(buf+3) << 8 | hexhex2bin(buf+5);
    htype = hexhex2bin(buf+7);
    for (i = 0;  i< hlen; i++){
      rbuf[i] = hexhex2bin(buf+9+i*2);
    }
    if (htype == 0){
      if (fin == 0 || fin == 1){
	if (haddr == sa){
	  l = 0;
	  while(l < hlen && (c0 = fgetc(fp)) != EOF){
	    rbuf[l] = (unsigned char)c0;
	    l++;
	  }
	  sa += l;
	}
	print_hexline(hlen, haddr, htype, rbuf);
      }
      if (fin == 0) for (i = 0; i < hlen; i++) s += rbuf[i];
    }
    if (htype != 0 && fin == 0){
      fin = 1;
    }
    if (fin == 1 && htype == 4){
      oaddr = hexhex2bin(buf+9) << 8 | hexhex2bin(buf+11);
      print_hexline(hlen, haddr, htype, rbuf);
      if (oaddr == 0x0020){
	fin = 2;
      }
    }
    else if (fin == 2){
      rbuf[0] = (s >> 8) & 0xff;
      rbuf[1] = s & 0xff;
      print_hexline(hlen, haddr, htype, rbuf);
      fin = 3;
    }
    else if (fin == 3){
      print_hexline(hlen, haddr, htype, rbuf);
    }
  }
}
