Logo Search packages:      
Sourcecode: odyssey version File versions

void HexFile_ihx8::read ( DataBuffer buf  )  [virtual]

Reads data from the hex file into the DataBuffer. This should only be called when the hex file has been opened for reading.

Parameters:
buf A DataBuffer to store the data in.
Exceptions:
logic_error If the hex file was opened for writing.
runtime_error Contains a textual description of the error.

Implements HexFile.

Definition at line 41 of file HexFile_ihx8.cxx.

References HexFile::fp, DataBuffer::get_wordsize(), and HexFile::mode.

                                       {
      if(this->mode == HEXFILE_WRITE)
            throw logic_error("Attempt to read a file which was opened for writing.");

      int count, type, cksum, offset, bufwordlen;
      unsigned long extbase;
      unsigned int addr, data;
      char in[100];
      char *p;

      extbase = 0;
      bufwordlen = (buf.get_wordsize() + 7) & ~7;
      while(fgets(in, sizeof(in), fp) != NULL) {
            for(p=in; *p; p++)
                  if((*p == '\n') || (*p == '\r')) { *p = 0; break; }

            if(sscanf(in, ":%02X%04X%02X", &count, &addr, &type) != 3) break;
            p = in + 9;

            cksum = (count & 0xff) + ((addr >> 8) & 0xff) +
              (addr & 0xff) + (type & 0xff);

            if(type == 0x01) {
                  /* End-of-file record */
                  return;
            } else if(type == 0x02) {
                  /* Extended segment address record */
                  if((count != 2) || (addr != 0))
                        throw runtime_error("Invalid extended segment address record.");
                  if(sscanf(p, "%04lX", &extbase) != 1) break;
                  cksum += (extbase & 0xff) + ((extbase >> 8) & 0xff);
                  p += 4;
                  extbase <<= 4;
                  goto check_cksum;
            } else if(type == 0x04) {
                  /* Extended linear address record */
                  if((count != 2) || (addr != 0))
                        throw runtime_error("Invalid extended linear address record.");
                  if(sscanf(p, "%04lX", &extbase) != 1) break;
                  cksum += (extbase & 0xff) + ((extbase >> 8) & 0xff);
                  p += 4;
                  extbase <<= 16;
                  goto check_cksum;
            } else if(type != 0x00) {
                  throw runtime_error("Unknown record type encountered.");
            }

            for(offset=0; offset<count; offset++) {
                  if(sscanf(p, "%02X", &data) == 0) goto corrupted;
                  cksum += ((data >> 8) & 0xff);
                  cksum += (data & 0xff);
                  p += 2;
                  switch(bufwordlen) {
                  case 8:
                        buf[extbase+addr+offset] = data;
                        break;
                  case 16:
                        if(((extbase+addr+offset) % 2) == 0) {
                              /* Low byte of the word */
                              buf[(extbase+addr+offset)/2] &= ~0x00ff;
                              buf[(extbase+addr+offset)/2] |= data;
                        } else {
                              /* High byte of the word */
                              buf[(extbase+addr+offset)/2] &= ~0xff00;
                              buf[(extbase+addr+offset)/2] |= (data << 8);
                        }
                        break;
                  default:
                        throw runtime_error("Unsupported data buffer word size.");
                  }
            }
check_cksum:;
            if(sscanf(p, "%02X", &data) == 0) break;
            if((unsigned int)((-cksum) & 0xff) != (data & 0xff))
                  throw runtime_error("Checksum error in hex file");
      }
corrupted:;
      throw runtime_error("Corrupted hex file");
}


Generated by  Doxygen 1.6.0   Back to index