1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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;
}
|