diff options
Diffstat (limited to 'xextest.c')
-rw-r--r-- | xextest.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/xextest.c b/xextest.c new file mode 100644 index 0000000..06614ab --- /dev/null +++ b/xextest.c @@ -0,0 +1,87 @@ +#include <stdio.h> +#include "xex.h" + +/* This is a minimal program illustrating the use of the xex library. + + It expects to read one or more Atari executables from standard + input, and writes one (possibly multi-segment) Atari executable + to standard output. + + This code is provided an an example only; for a useful real-world + tool, use xexcat. + + To compile: "make xextest" if you have the full bw_atari8_utils + source distribution. Otherwise, (assuming you at least have xex.c + and xex.h): gcc -o xextest xextest.c xex.c (should work with other + compilers too). + */ + +int main(int argc, char **argv) { + xex_segment seg; + unsigned char buffer[64 * 1024]; /* 64K buffer is guaranteed big enough */ + int count = 1; + + /* tell xex library to emit debugging trace to stderr. Default value + is 0 (no trace). */ + xex_verbose = 1; + + /* xex_fread_seg_header() returns false on error or at EOF. */ + while(xex_fread_seg_header(&seg, stdin)) { + seg.object = buffer; + + /* We're using a static buffer here. If we were using dynamically + allocated buffers, we'd say "seg.object = malloc(seg.len)" above, + and put a "free(seg.object)" somewhere after the xex_fwrite_seg(). + + Note that the xex lib NEVER calls malloc() or free() itself. + + (Also, it never calls any of the standard I/O functions except + fread(), fwrite(), feof(), or ferror(); you have to fopen() and + fclose() in the calling code). + */ + + /* xex library doesn't care if the first segment is missing the + required Atari $FFFF header, so we handle it ourselves. */ + if(count == 1 && !seg.has_ff_header) + fprintf(stderr, "missing initial $FFFF header (bad XEX file?)\n"); + + /* Force the first segment to have a $FFFF header, and remove the + (optional) $FFFF header from subsequent segments. */ + seg.has_ff_header = (count == 1); + + /* Read the segment data. xex_fread_seg_data() returns false for + failure (with xex_errno set to indicate the reason). An EOF in the + middle of a segment is an error (means the file was truncated). */ + if(!xex_fread_seg_data(&seg, stdin)) + break; + + /* xex_fwrite_seg() returns true for success, or false for failure + (with xex_errno set). Unless you've diddled with seg's fields, + xex_errno will always be XERR_SYSCALL when xex_fwrite_seg() + fails (and xex_perror() or xex_strerror() will call the real + strerror() to get the system's error message). */ + if(!xex_fwrite_seg(&seg, stdout)) + break; + + /* If we weren't using xex_verbose mode, we might want to call + xex_print_seg_info() ourselves to print some info about the + segment, like so: */ + + /* xex_print_seg_info(&seg); */ + + fprintf(stderr, "segment #%d done\n\n", count); + count++; + } + + /* If xex_fread_seg_header() returned false due to EOF, xex_errno will + be zero (aka XERR_NONE). Otherwise, xex_fread_seg_header() didn't like + the header, or else xex_fread_seg_data() returned false (probably + due to a premature EOF in the middle of the segment data), so we print + an error message about it. */ + if(xex_errno) + xex_perror("error"); + + /* xex_errno will be 0 for error or non-zero otherwise, so it's suitable + for use as a standard UNIX exit status. */ + return xex_errno; +} |