aboutsummaryrefslogtreecommitdiff
path: root/xextest.c
diff options
context:
space:
mode:
Diffstat (limited to 'xextest.c')
-rw-r--r--xextest.c87
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;
+}