A small C library for reading Intel HEX, Motorola SREC, and possibly more in the future.
All these formats are for storing programs as text using hexidecimal bytes. You can read all about them on Wikipedia:
FILE *file = fopen("example.hex", "r");
char buf[IHR_MAX_SIZE];
int reclen;
struct ihr_record rec;
size_t size;
char *line;
do {
line = fgetln(file, &size); /* This is valid until next call. */
/* The buffer is filled if the record has type 0 (data): */
rec.data.data = buf;
/* Read the line as an I8HEX record: */
if ((reclen = ihr_read(IHRT_I8, size, line, &rec)) < 0) {
/* ~reclen is the column; -rec.type is the error code: */
do_error(&rec, ~reclen);
} else {
use_record(&rec);
}
} while (rec.type != IHRR_I_END_OF_FILE);
fclose(file);To use this library, you can probably just copy the header file into some header directory and the source file into your source directory. It should compile with ANSI C.
There is only one function in the API, although it is somewhat complex:
int ihr_read(
int file_type,
size_t len,
const char *text,
struct ihr_record *rec);This function reads text-encoded data from text, which is assumed to be of
length len. No string terminator is necessary.
Before you call the function, you must set rec->data.data to a buffer at
least IHR_MAX_SIZE bytes in width (the maximum data entry length.) rec
points to a structure with this format:
struct ihr_record {
char type;
IHR_U8 size;
IHR_U32 addr;
union {
IHR_U8 *data;
union {
IHR_U16 base_addr;
IHR_U32 ext_instr_ptr;
struct {
IHR_U16 code_seg;
IHR_U16 instr_ptr;
} start;
} ihex;
} data;
};The types called things like IHR_U8 are just unsigned integers of a certain
width (8 bits in this case.) You can read about the format of a record in the
Wikipedia link from the introduction, but here is a summary of the fields:
typeis the record type. The possible values are as follows:IHRR_DATAis Data.IHRR_END_OF_FILEis End of FileIHRR_EXT_SEG_ADDRis Extended Segment Address.IHRR_START_SEG_ADDRis Start Segment Address.IHRR_EXT_LIN_ADDRis Extended Linear Address.IHRR_START_LIN_ADDRis Start Linear Address.
sizeis the byte count.addris the address.datais a bunch of bytes, the number of which is indicated bysize. The members of its union:datais just raw bytes. This field is associated with the Data record type. The library does no allocation, which is why you must set this to an empty buffer beforehand.ihexcontains options specific to Intel HEX:base_addris associated with either one of the Extended Segment Address or Extended Linear Address types. The meaning of the address is different, but the data can be stored the same way.ext_instr_ptrcorresponds with the Start Linear Address type.startcorresponds with the Start Segment Address type. Itscode_segfield is the start of the code segment, while itsinstr_ptrfield is the initial instruction pointer position.
The file_type field describes the subset of the format to use. The subset
restricts which field types are valid.
IHRT_I8is I8HEXIHRT_I16is I32HEXIHRT_I32is I32HEXIHRT_S19is SREC S19IHRT_S28is SREC S28IHRT_S37is SREC S37
The return value of the function is positive on success or negative on error. If
it is positive, it indicates how much of the text was read as part of the
record. If it is negative, ~line (not -, but ~) indicates the erroneous
part of the text. On error, the type of the record is set to a negated error
value. No other data can be read from the record. Here are possible errors with
their descriptions:
IHRE_EXPECTED_EOL: Record does not end with\nor\r\n.IHRE_INVALID_CHECKSUM: The checksum of the record did not match its computed checksum.IHRE_INVALID_SIZE: The byte count of the record was not correct.IHRE_INVALID_TYPE: The type of the record was not valid.IHRE_MISSING_COLON: The:which must begin every record was not present.IHRE_NOT_HEX: A pair of bytes could not be parsed as a hexidecimal number.IHRE_SUB_MIN_LENGTH: The givenlenis belowIHR_MIN_LENGTH, the minimum text-encoded record length.