added "!outfilestart" and "!outfilelimit". made "--from-to" to use end+1 instead of end.
git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@335 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
17
src/acme.c
17
src/acme.c
@@ -130,7 +130,7 @@ static void show_help_and_exit(void)
|
|||||||
" --" OPTION_LABELDUMP " (old name for --" OPTION_SYMBOLLIST ")\n"
|
" --" OPTION_LABELDUMP " (old name for --" OPTION_SYMBOLLIST ")\n"
|
||||||
" --" OPTION_VICELABELS " FILE set file name for label dump in VICE format\n"
|
" --" OPTION_VICELABELS " FILE set file name for label dump in VICE format\n"
|
||||||
" --" OPTION_SETPC " VALUE set program counter\n"
|
" --" OPTION_SETPC " VALUE set program counter\n"
|
||||||
" --" OPTION_FROM_TO " VALUE VALUE set start and end of output file\n"
|
" --" OPTION_FROM_TO " VALUE VALUE set start and end+1 of output file\n"
|
||||||
" --" OPTION_CPU " CPU set target processor\n"
|
" --" OPTION_CPU " CPU set target processor\n"
|
||||||
" --" OPTION_INITMEM " VALUE define 'empty' memory\n"
|
" --" OPTION_INITMEM " VALUE define 'empty' memory\n"
|
||||||
" --" OPTION_MAXERRORS " NUMBER set number of errors before exiting\n"
|
" --" OPTION_MAXERRORS " NUMBER set number of errors before exiting\n"
|
||||||
@@ -533,7 +533,7 @@ static const char *long_option(const char *string)
|
|||||||
config.initial_pc = string_to_nonneg_number(cliargs_safe_get_next("program counter"));
|
config.initial_pc = string_to_nonneg_number(cliargs_safe_get_next("program counter"));
|
||||||
else if (strcmp(string, OPTION_FROM_TO) == 0) {
|
else if (strcmp(string, OPTION_FROM_TO) == 0) {
|
||||||
config.outfile_start = string_to_nonneg_number(cliargs_safe_get_next("start address of output file"));
|
config.outfile_start = string_to_nonneg_number(cliargs_safe_get_next("start address of output file"));
|
||||||
config.outfile_end = string_to_nonneg_number(cliargs_safe_get_next("end address of output file"));
|
config.outfile_limit = string_to_nonneg_number(cliargs_safe_get_next("end+1 of output file"));
|
||||||
} else if (strcmp(string, OPTION_CPU) == 0)
|
} else if (strcmp(string, OPTION_CPU) == 0)
|
||||||
set_starting_cpu(cliargs_get_next()); // NULL is ok (handled like unknown)
|
set_starting_cpu(cliargs_get_next()); // NULL is ok (handled like unknown)
|
||||||
else if (strcmp(string, OPTION_INITMEM) == 0)
|
else if (strcmp(string, OPTION_INITMEM) == 0)
|
||||||
@@ -553,7 +553,7 @@ static const char *long_option(const char *string)
|
|||||||
else if (strcmp(string, OPTION_IGNORE_ZEROES) == 0)
|
else if (strcmp(string, OPTION_IGNORE_ZEROES) == 0)
|
||||||
config.honor_leading_zeroes = FALSE;
|
config.honor_leading_zeroes = FALSE;
|
||||||
else if (strcmp(string, OPTION_STRICT_SEGMENTS) == 0)
|
else if (strcmp(string, OPTION_STRICT_SEGMENTS) == 0)
|
||||||
config.segment_warning_is_error = TRUE;
|
config.debuglevel_segmentprobs = DEBUGLEVEL_ERROR;
|
||||||
else if (strcmp(string, OPTION_STRICT) == 0)
|
else if (strcmp(string, OPTION_STRICT) == 0)
|
||||||
config.all_warnings_are_errors = TRUE;
|
config.all_warnings_are_errors = TRUE;
|
||||||
else if (strcmp(string, OPTION_DIALECT) == 0)
|
else if (strcmp(string, OPTION_DIALECT) == 0)
|
||||||
@@ -668,12 +668,15 @@ int main(int argc, const char *argv[])
|
|||||||
fprintf(stderr, "%sStart address of output file exceeds outbuffer size.\n", cliargs_error);
|
fprintf(stderr, "%sStart address of output file exceeds outbuffer size.\n", cliargs_error);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if ((config.outfile_end != NO_VALUE_GIVEN) && (config.outfile_end >= config.outbuf_size)) {
|
// "limit" is end+1 and therefore we need ">" instead of ">=":
|
||||||
fprintf(stderr, "%sEnd address of output file exceeds outbuffer size.\n", cliargs_error);
|
if ((config.outfile_limit != NO_VALUE_GIVEN) && (config.outfile_limit > config.outbuf_size)) {
|
||||||
|
fprintf(stderr, "%sEnd+1 of output file exceeds outbuffer size.\n", cliargs_error);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (config.outfile_start > config.outfile_end) {
|
if ((config.outfile_start != NO_VALUE_GIVEN)
|
||||||
fprintf(stderr, "%sStart address of output file exceeds end address.\n", cliargs_error);
|
&& (config.outfile_limit != NO_VALUE_GIVEN)
|
||||||
|
&& (config.outfile_start >= config.outfile_limit)) {
|
||||||
|
fprintf(stderr, "%sStart address of output file exceeds end+1.\n", cliargs_error);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ void config_default(struct config *conf)
|
|||||||
conf->format_color = FALSE; // enabled by --color
|
conf->format_color = FALSE; // enabled by --color
|
||||||
conf->msg_stream = stderr; // set to stdout by --use-stdout
|
conf->msg_stream = stderr; // set to stdout by --use-stdout
|
||||||
conf->honor_leading_zeroes = TRUE; // disabled by --ignore-zeroes
|
conf->honor_leading_zeroes = TRUE; // disabled by --ignore-zeroes
|
||||||
conf->segment_warning_is_error = FALSE; // enabled by --strict-segments TODO - toggle default?
|
conf->debuglevel_segmentprobs = DEBUGLEVEL_WARNING; // changed to ERROR by --strict-segments TODO - toggle default?
|
||||||
conf->all_warnings_are_errors = FALSE; // enabled by --strict
|
conf->all_warnings_are_errors = FALSE; // enabled by --strict
|
||||||
conf->test_new_features = FALSE; // enabled by --test
|
conf->test_new_features = FALSE; // enabled by --test
|
||||||
conf->wanted_version = VER_CURRENT; // changed by --dialect
|
conf->wanted_version = VER_CURRENT; // changed by --dialect
|
||||||
@@ -126,7 +126,7 @@ void config_default(struct config *conf)
|
|||||||
conf->mem_init_value = MEMINIT_USE_DEFAULT; // set by --initmem
|
conf->mem_init_value = MEMINIT_USE_DEFAULT; // set by --initmem
|
||||||
conf->initial_pc = NO_VALUE_GIVEN; // set by --setpc
|
conf->initial_pc = NO_VALUE_GIVEN; // set by --setpc
|
||||||
conf->outfile_start = NO_VALUE_GIVEN; // set by --from-to
|
conf->outfile_start = NO_VALUE_GIVEN; // set by --from-to
|
||||||
conf->outfile_end = NO_VALUE_GIVEN; // set by --from-to
|
conf->outfile_limit = NO_VALUE_GIVEN; // end+1, set by --from-to
|
||||||
}
|
}
|
||||||
|
|
||||||
// memory allocation stuff
|
// memory allocation stuff
|
||||||
|
|||||||
22
src/global.h
22
src/global.h
@@ -60,6 +60,15 @@ enum version {
|
|||||||
// ignore leading zeroes?
|
// ignore leading zeroes?
|
||||||
VER_FUTURE // far future
|
VER_FUTURE // far future
|
||||||
};
|
};
|
||||||
|
enum debuglevel {
|
||||||
|
DEBUGLEVEL_SERIOUS = -3, // ACME stops right away
|
||||||
|
DEBUGLEVEL_ERROR = -2, // something is wrong
|
||||||
|
DEBUGLEVEL_WARNING = -1, // something looks wrong
|
||||||
|
DEBUGLEVEL_INFO = 0, // info msg ("173 bytes left in code area!")
|
||||||
|
DEBUGLEVEL_DEBUG = 1 // debug msg
|
||||||
|
// debug messages with higher levels are suppressed,
|
||||||
|
// can be changed using "--debuglevel" cli switch.
|
||||||
|
};
|
||||||
// configuration
|
// configuration
|
||||||
struct config {
|
struct config {
|
||||||
char pseudoop_prefix; // '!' or '.'
|
char pseudoop_prefix; // '!' or '.'
|
||||||
@@ -72,7 +81,7 @@ struct config {
|
|||||||
boolean format_color; // enabled by --color
|
boolean format_color; // enabled by --color
|
||||||
FILE *msg_stream; // defaults to stderr, changed to stdout by --use-stdout
|
FILE *msg_stream; // defaults to stderr, changed to stdout by --use-stdout
|
||||||
boolean honor_leading_zeroes; // TRUE, disabled by --ignore-zeroes
|
boolean honor_leading_zeroes; // TRUE, disabled by --ignore-zeroes
|
||||||
boolean segment_warning_is_error; // FALSE, enabled by --strict-segments
|
enum debuglevel debuglevel_segmentprobs; // WARNING, changed to ERROR by --strict-segments
|
||||||
boolean all_warnings_are_errors; // FALSE, enabled by --strict
|
boolean all_warnings_are_errors; // FALSE, enabled by --strict
|
||||||
boolean test_new_features; // FALSE, enabled by --test
|
boolean test_new_features; // FALSE, enabled by --test
|
||||||
enum version wanted_version; // set by --dialect (and --test --test)
|
enum version wanted_version; // set by --dialect (and --test --test)
|
||||||
@@ -83,7 +92,7 @@ struct config {
|
|||||||
#define NO_VALUE_GIVEN (-1) // default value for these fields if cli switch not used:
|
#define NO_VALUE_GIVEN (-1) // default value for these fields if cli switch not used:
|
||||||
signed long initial_pc; // set by --setpc
|
signed long initial_pc; // set by --setpc
|
||||||
signed long outfile_start; // set by --from-to
|
signed long outfile_start; // set by --from-to
|
||||||
signed long outfile_end; // set by --from-to
|
signed long outfile_limit; // end+1, set by --from-to
|
||||||
};
|
};
|
||||||
extern struct config config;
|
extern struct config config;
|
||||||
|
|
||||||
@@ -163,15 +172,6 @@ extern void parse_until_eob_or_eof(void);
|
|||||||
// Don't forget to call EnsureEOL() afterwards.
|
// Don't forget to call EnsureEOL() afterwards.
|
||||||
extern int parse_optional_block(void);
|
extern int parse_optional_block(void);
|
||||||
|
|
||||||
enum debuglevel {
|
|
||||||
DEBUGLEVEL_SERIOUS = -3, // ACME stops right away
|
|
||||||
DEBUGLEVEL_ERROR = -2, // something is wrong
|
|
||||||
DEBUGLEVEL_WARNING = -1, // something looks wrong
|
|
||||||
DEBUGLEVEL_INFO = 0, // info msg ("173 bytes left in code area!")
|
|
||||||
DEBUGLEVEL_DEBUG = 1 // debug msg
|
|
||||||
// debug messages with higher levels are suppressed,
|
|
||||||
// can be changed using "--debuglevel" cli switch.
|
|
||||||
};
|
|
||||||
// generate a debug/info/warning/error message
|
// generate a debug/info/warning/error message
|
||||||
void throw_message(enum debuglevel level, const char msg[]);
|
void throw_message(enum debuglevel level, const char msg[]);
|
||||||
|
|
||||||
|
|||||||
63
src/output.c
63
src/output.c
@@ -42,7 +42,7 @@ struct output {
|
|||||||
intval_t write_idx; // index of next write
|
intval_t write_idx; // index of next write
|
||||||
intval_t lowest_written; // smallest address used
|
intval_t lowest_written; // smallest address used
|
||||||
intval_t highest_written; // largest address used
|
intval_t highest_written; // largest address used
|
||||||
boolean initvalue_set;
|
boolean initvalue_set; // default byte value for buffer has been set
|
||||||
struct {
|
struct {
|
||||||
intval_t start; // start of current segment (or NO_SEGMENT_START)
|
intval_t start; // start of current segment (or NO_SEGMENT_START)
|
||||||
intval_t max; // highest address segment may use
|
intval_t max; // highest address segment may use
|
||||||
@@ -123,11 +123,7 @@ static void border_crossed(int current_offset)
|
|||||||
Throw_serious_error("Produced too much code.");
|
Throw_serious_error("Produced too much code.");
|
||||||
// TODO - get rid of FIRST_PASS condition, because user can suppress these warnings if they want
|
// TODO - get rid of FIRST_PASS condition, because user can suppress these warnings if they want
|
||||||
if (FIRST_PASS) {
|
if (FIRST_PASS) {
|
||||||
// TODO: make warn/err an arg for a general "Throw" function
|
throw_message(config.debuglevel_segmentprobs, "Segment reached another one, overwriting it.");
|
||||||
if (config.segment_warning_is_error)
|
|
||||||
Throw_error("Segment reached another one, overwriting it.");
|
|
||||||
else
|
|
||||||
Throw_warning("Segment reached another one, overwriting it.");
|
|
||||||
find_segment_max(current_offset + 1); // find new (next) limit
|
find_segment_max(current_offset + 1); // find new (next) limit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -233,6 +229,32 @@ int output_setdefault(char content)
|
|||||||
return 0; // ok
|
return 0; // ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remember current outbuf index as start/limit of output file
|
||||||
|
static boolean force_file_start = FALSE;
|
||||||
|
static intval_t forced_start_idx;
|
||||||
|
void outbuf_set_outfile_start(void)
|
||||||
|
{
|
||||||
|
// check whether ptr undefined
|
||||||
|
if (output_byte == no_output) {
|
||||||
|
Throw_error(exception_pc_undefined);
|
||||||
|
} else {
|
||||||
|
force_file_start = TRUE;
|
||||||
|
forced_start_idx = out->write_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static boolean force_file_limit = FALSE;
|
||||||
|
static intval_t forced_limit_idx;
|
||||||
|
void outbuf_set_outfile_limit(void)
|
||||||
|
{
|
||||||
|
// check whether ptr undefined
|
||||||
|
if (output_byte == no_output) {
|
||||||
|
Throw_error(exception_pc_undefined);
|
||||||
|
} else {
|
||||||
|
force_file_limit = TRUE;
|
||||||
|
forced_limit_idx = out->write_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// try to set output format held in DynaBuf. Returns zero on success.
|
// try to set output format held in DynaBuf. Returns zero on success.
|
||||||
int outputfile_set_format(void)
|
int outputfile_set_format(void)
|
||||||
@@ -298,29 +320,35 @@ void output_createbuffer(void)
|
|||||||
void output_save_file(FILE *fd)
|
void output_save_file(FILE *fd)
|
||||||
{
|
{
|
||||||
intval_t start,
|
intval_t start,
|
||||||
end,
|
limit, // end+1
|
||||||
amount;
|
amount;
|
||||||
|
|
||||||
start = out->lowest_written;
|
start = out->lowest_written;
|
||||||
end = out->highest_written;
|
limit = out->highest_written + 1;
|
||||||
// if cli args were given, they override the actual values:
|
// if pseudo opcodes were used, they override the actual values:
|
||||||
|
if (force_file_start)
|
||||||
|
start = forced_start_idx;
|
||||||
|
if (force_file_limit)
|
||||||
|
limit = forced_limit_idx;
|
||||||
|
// if cli args were given, they override even harder:
|
||||||
if (config.outfile_start != NO_VALUE_GIVEN)
|
if (config.outfile_start != NO_VALUE_GIVEN)
|
||||||
start = config.outfile_start;
|
start = config.outfile_start;
|
||||||
if (config.outfile_end != NO_VALUE_GIVEN)
|
if (config.outfile_limit != NO_VALUE_GIVEN)
|
||||||
end = config.outfile_end;
|
limit = config.outfile_limit;
|
||||||
|
|
||||||
if (end < start) {
|
if (limit <= start) {
|
||||||
// nothing written
|
// nothing written
|
||||||
start = 0; // I could try to use some segment start, but what for?
|
start = 0; // I could try to use some segment start, but what for?
|
||||||
amount = 0;
|
amount = 0;
|
||||||
// FIXME - how about not writing anything in this case?
|
// FIXME - how about not writing anything in this case?
|
||||||
// a CBM file would consist of a bogus load address and nothing else!
|
// a CBM file would consist of a bogus load address and nothing else!
|
||||||
} else {
|
} else {
|
||||||
amount = end - start + 1;
|
amount = limit - start;
|
||||||
}
|
}
|
||||||
if (config.process_verbosity)
|
if (config.process_verbosity) {
|
||||||
printf("Saving %ld (0x%lx) bytes (0x%lx - 0x%lx exclusive).\n",
|
printf("Saving %ld (0x%04lx) bytes (0x%04lx - 0x%04lx exclusive).\n",
|
||||||
amount, amount, start, start + amount);
|
amount, amount, start, start + amount);
|
||||||
|
}
|
||||||
// output file header according to file format
|
// output file header according to file format
|
||||||
// FIXME - add checks and error messages for "start is above $ffff"!)
|
// FIXME - add checks and error messages for "start is above $ffff"!)
|
||||||
switch (output_format) {
|
switch (output_format) {
|
||||||
@@ -386,10 +414,7 @@ static void check_segment(intval_t new_pc)
|
|||||||
while (test_segment->start <= new_pc) {
|
while (test_segment->start <= new_pc) {
|
||||||
if ((test_segment->start + test_segment->length) > new_pc) {
|
if ((test_segment->start + test_segment->length) > new_pc) {
|
||||||
// TODO - include overlap size in error message!
|
// TODO - include overlap size in error message!
|
||||||
if (config.segment_warning_is_error)
|
throw_message(config.debuglevel_segmentprobs, "Segment starts inside another one, overwriting it.");
|
||||||
Throw_error("Segment starts inside another one, overwriting it.");
|
|
||||||
else
|
|
||||||
Throw_warning("Segment starts inside another one, overwriting it.");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ extern struct vcpu CPU_state; // current CPU state FIXME - restrict visibility t
|
|||||||
// Prototypes
|
// Prototypes
|
||||||
|
|
||||||
// clear segment list and disable output
|
// clear segment list and disable output
|
||||||
//TODO - does this belong to outbuf stuff?
|
|
||||||
extern void output_passinit(void);
|
extern void output_passinit(void);
|
||||||
|
|
||||||
|
|
||||||
@@ -58,6 +57,9 @@ extern void (*output_byte)(intval_t);
|
|||||||
// returns zero if ok, nonzero if already set
|
// returns zero if ok, nonzero if already set
|
||||||
extern int output_setdefault(char content);
|
extern int output_setdefault(char content);
|
||||||
|
|
||||||
|
// remember current outbuf index as start/limit of output file
|
||||||
|
extern void outbuf_set_outfile_start(void);
|
||||||
|
extern void outbuf_set_outfile_limit(void);
|
||||||
|
|
||||||
// outfile stuff:
|
// outfile stuff:
|
||||||
|
|
||||||
|
|||||||
@@ -1372,6 +1372,35 @@ static enum eos po_serious(void)
|
|||||||
return throw_src_string(DEBUGLEVEL_SERIOUS, "!serious: ");
|
return throw_src_string(DEBUGLEVEL_SERIOUS, "!serious: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// use current outbuf index as "first byte of output file"
|
||||||
|
static enum eos po_outfilestart(void)
|
||||||
|
{
|
||||||
|
static int last_pass_number = -1;
|
||||||
|
|
||||||
|
if ((config.outfile_start != NO_VALUE_GIVEN)
|
||||||
|
|| (last_pass_number == pass.number)) {
|
||||||
|
Throw_first_pass_warning("Start of output file already chosen.");
|
||||||
|
} else {
|
||||||
|
last_pass_number = pass.number;
|
||||||
|
outbuf_set_outfile_start();
|
||||||
|
}
|
||||||
|
return ENSURE_EOS;
|
||||||
|
}
|
||||||
|
// use current outbuf index as "end+1 of output file"
|
||||||
|
static enum eos po_outfilelimit(void)
|
||||||
|
{
|
||||||
|
static int last_pass_number = -1;
|
||||||
|
|
||||||
|
if ((config.outfile_limit != NO_VALUE_GIVEN)
|
||||||
|
|| (last_pass_number == pass.number)) {
|
||||||
|
Throw_first_pass_warning("End of output file already chosen.");
|
||||||
|
} else {
|
||||||
|
last_pass_number = pass.number;
|
||||||
|
outbuf_set_outfile_limit();
|
||||||
|
}
|
||||||
|
return ENSURE_EOS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// end of source file ("!endoffile" or "!eof")
|
// end of source file ("!endoffile" or "!eof")
|
||||||
static enum eos po_endoffile(void)
|
static enum eos po_endoffile(void)
|
||||||
@@ -1455,8 +1484,8 @@ static struct ronode pseudo_opcode_tree[] = {
|
|||||||
PREDEFNODE("warn", po_warn),
|
PREDEFNODE("warn", po_warn),
|
||||||
PREDEFNODE("error", po_error),
|
PREDEFNODE("error", po_error),
|
||||||
PREDEFNODE("serious", po_serious),
|
PREDEFNODE("serious", po_serious),
|
||||||
// PREDEFNODE("filestart", po_),
|
PREDEFNODE("outfilestart", po_outfilestart),
|
||||||
// PREDEFNODE("filestop", po_),
|
PREDEFNODE("outfilelimit", po_outfilelimit),
|
||||||
PREDEFNODE("eof", po_endoffile),
|
PREDEFNODE("eof", po_endoffile),
|
||||||
PREDEF_END("endoffile", po_endoffile),
|
PREDEF_END("endoffile", po_endoffile),
|
||||||
// ^^^^ this marks the last element
|
// ^^^^ this marks the last element
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#define RELEASE "0.97" // update before release FIXME
|
#define RELEASE "0.97" // update before release FIXME
|
||||||
#define CODENAME "Zem" // update before release
|
#define CODENAME "Zem" // update before release
|
||||||
#define CHANGE_DATE "11 Feb" // update before release FIXME
|
#define CHANGE_DATE "12 Feb" // update before release FIXME
|
||||||
#define CHANGE_YEAR "2024" // update before release
|
#define CHANGE_YEAR "2024" // update before release
|
||||||
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/"
|
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/"
|
||||||
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
|
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
|
||||||
|
|||||||
Reference in New Issue
Block a user