Source file: /~heha/enas/Convac-Ätzer/uba.zip/src/loadhex.cpp

#include "loadhex.h"
#include <setjmp.h>
#include <stdio.h>

struct Hexfile {
 const char*text,*end;
 int line;
 jmp_buf env;
 unsigned linaddr;
 enum{ MAXLEN=32 };
 Hexfile(const char*t,unsigned l):text(t),end(t+l),line(1) {}
 char readChar() {
  if (text==end) longjmp(env,2);	// Fehler: EOF
  char c=*text++;
  if (c=='\n') ++line;			// Zeile mitzählen
  return c;
 }
 byte readNibble() {
  char c=readChar();
  if (c>=0x40) c&=~0x20;
  if (c<'0' || (c>'9' && c<'A') || c>'F') longjmp(env,3);	// Fehler: Falsches Ziffernzeichen
  c-='0'; if (c>9) c-='A'-'9'-1;	// 0..15
  return c;
 }
 byte readByte() {return readNibble()<<4|readNibble();}
 char readLine(byte buf[]) {
  char c;
  do c=readChar(); while (c!=':' && c!='S');
  if (c==':') {			// Intel-Hex
   byte cs=buf[0]=readByte();
   if (cs>32) longjmp(env,4);	// Fehler: Zu lange Zeilenlänge
   for (int i=1; i<buf[0]+5; i++) cs+=buf[i]=readByte();
   if (cs) longjmp(env,5);	// Fehler: Falsche Prüfsumme
  }else{			// Motorola-Hex (S-Hex)
   buf[0]=readNibble();
   byte cs=buf[1]=readByte();
   if (cs>35) longjmp(env,4);	// Zu lange (hier nicht unterstützte) Zeilenlänge
   for (int i=2; i<buf[1]; i++) cs+=buf[i]=readByte();
   if (cs!=0xFF) longjmp(env,5);
  }
  return c;
 }
 int load(bool eeprom) {
  linaddr=eeprom?0x810000:0;
  int ret=setjmp(env);
  if (ret) return ret;		// Fehler
  byte buf[MAXLEN+5];		// 5 = Länge+AddresseH+AdresseL+Typ+Prüfsumme
  for(;;) {
   buf[3]=0xFF;
   switch (readLine(buf)) {
    case ':': {
     unsigned addr=buf[1]<<8|buf[2];
     if (buf[3]&&addr) longjmp(env,8);	// Außer für Daten ist eine Adresse nicht erlaubt
     switch (buf[3]) {
      case 0: store_buffer(buf+4,buf[0],linaddr+addr); break;
      case 1: return 0;		// Erfolgreiches Ende
      case 2: if (buf[0]!=2) longjmp(env,7);	// Falsche Nutzdatenlänge
        linaddr=(buf[4]<<8|buf[5])<<4;
      break;
      case 3:
      case 5: if (buf[0]!=4) longjmp(env,7);	// Falsche Nutzdatenlänge
      break;
      case 4: if (buf[0]!=2) longjmp(env,7);	// Falsche Nutzdatenlänge
        linaddr=(buf[4]<<8|buf[5])<<16;
      default:longjmp(env,6);	// unbekannter Satztyp
     }
    }break;
    case 'S': {
     int adrlen=0;
     switch (buf[0]) {
      case 0: break;
      case 1: adrlen=2; break;
      case 2: adrlen=3; break;
      case 3: adrlen=4; break;
      case 4: break;
      case 5:
      case 6:
      case 7: return 0;
      default: longjmp(env,6);
     }
     if (adrlen) {
      if (buf[1]<=adrlen+2) longjmp(env,7);
      unsigned addr=0;
      for (int i=0; i<adrlen; i++) {
       addr=addr<<8|buf[2+i];
      }
      store_buffer(buf+2+adrlen,buf[1]-2-adrlen,addr);
     }
    }break;
   }
  }
 }
};


bool loadhex(const byte*text,unsigned len,bool eeprom) {
 Hexfile f(reinterpret_cast<const char*>(text),len);
 int e=f.load(eeprom);
 if (e) fprintf(stderr,"Error %d loading hex file at line %d!",e,f.line);
 return !e;
}
Detected encoding: ANSI (CP1252)4
Wrong umlauts? - Assume file is ANSI (CP1252) encoded