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:
marcobaye 2024-02-13 00:08:17 +00:00
parent f52430f620
commit 444c7e858f
7 changed files with 102 additions and 43 deletions

View File

@ -130,7 +130,7 @@ static void show_help_and_exit(void)
" --" OPTION_LABELDUMP " (old name for --" OPTION_SYMBOLLIST ")\n"
" --" OPTION_VICELABELS " FILE set file name for label dump in VICE format\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_INITMEM " VALUE define 'empty' memory\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"));
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_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)
set_starting_cpu(cliargs_get_next()); // NULL is ok (handled like unknown)
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)
config.honor_leading_zeroes = FALSE;
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)
config.all_warnings_are_errors = TRUE;
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);
exit(EXIT_FAILURE);
}
if ((config.outfile_end != NO_VALUE_GIVEN) && (config.outfile_end >= config.outbuf_size)) {
fprintf(stderr, "%sEnd address of output file exceeds outbuffer size.\n", cliargs_error);
// "limit" is end+1 and therefore we need ">" instead of ">=":
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);
}
if (config.outfile_start > config.outfile_end) {
fprintf(stderr, "%sStart address of output file exceeds end address.\n", cliargs_error);
if ((config.outfile_start != NO_VALUE_GIVEN)
&& (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);
}

View File

@ -117,7 +117,7 @@ void config_default(struct config *conf)
conf->format_color = FALSE; // enabled by --color
conf->msg_stream = stderr; // set to stdout by --use-stdout
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->test_new_features = FALSE; // enabled by --test
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->initial_pc = NO_VALUE_GIVEN; // set by --setpc
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

View File

@ -60,6 +60,15 @@ enum version {
// ignore leading zeroes?
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
struct config {
char pseudoop_prefix; // '!' or '.'
@ -72,7 +81,7 @@ struct config {
boolean format_color; // enabled by --color
FILE *msg_stream; // defaults to stderr, changed to stdout by --use-stdout
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 test_new_features; // FALSE, enabled by --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:
signed long initial_pc; // set by --setpc
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;
@ -163,15 +172,6 @@ extern void parse_until_eob_or_eof(void);
// Don't forget to call EnsureEOL() afterwards.
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
void throw_message(enum debuglevel level, const char msg[]);

View File

@ -42,7 +42,7 @@ struct output {
intval_t write_idx; // index of next write
intval_t lowest_written; // smallest address used
intval_t highest_written; // largest address used
boolean initvalue_set;
boolean initvalue_set; // default byte value for buffer has been set
struct {
intval_t start; // start of current segment (or NO_SEGMENT_START)
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.");
// TODO - get rid of FIRST_PASS condition, because user can suppress these warnings if they want
if (FIRST_PASS) {
// TODO: make warn/err an arg for a general "Throw" function
if (config.segment_warning_is_error)
Throw_error("Segment reached another one, overwriting it.");
else
Throw_warning("Segment reached another one, overwriting it.");
throw_message(config.debuglevel_segmentprobs, "Segment reached another one, overwriting it.");
find_segment_max(current_offset + 1); // find new (next) limit
}
}
@ -233,6 +229,32 @@ int output_setdefault(char content)
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.
int outputfile_set_format(void)
@ -298,29 +320,35 @@ void output_createbuffer(void)
void output_save_file(FILE *fd)
{
intval_t start,
end,
limit, // end+1
amount;
start = out->lowest_written;
end = out->highest_written;
// if cli args were given, they override the actual values:
limit = out->highest_written + 1;
// 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)
start = config.outfile_start;
if (config.outfile_end != NO_VALUE_GIVEN)
end = config.outfile_end;
if (config.outfile_limit != NO_VALUE_GIVEN)
limit = config.outfile_limit;
if (end < start) {
if (limit <= start) {
// nothing written
start = 0; // I could try to use some segment start, but what for?
amount = 0;
// FIXME - how about not writing anything in this case?
// a CBM file would consist of a bogus load address and nothing else!
} else {
amount = end - start + 1;
amount = limit - start;
}
if (config.process_verbosity)
printf("Saving %ld (0x%lx) bytes (0x%lx - 0x%lx exclusive).\n",
if (config.process_verbosity) {
printf("Saving %ld (0x%04lx) bytes (0x%04lx - 0x%04lx exclusive).\n",
amount, amount, start, start + amount);
}
// output file header according to file format
// FIXME - add checks and error messages for "start is above $ffff"!)
switch (output_format) {
@ -386,10 +414,7 @@ static void check_segment(intval_t new_pc)
while (test_segment->start <= new_pc) {
if ((test_segment->start + test_segment->length) > new_pc) {
// TODO - include overlap size in error message!
if (config.segment_warning_is_error)
Throw_error("Segment starts inside another one, overwriting it.");
else
Throw_warning("Segment starts inside another one, overwriting it.");
throw_message(config.debuglevel_segmentprobs, "Segment starts inside another one, overwriting it.");
return;
}

View File

@ -36,7 +36,6 @@ extern struct vcpu CPU_state; // current CPU state FIXME - restrict visibility t
// Prototypes
// clear segment list and disable output
//TODO - does this belong to outbuf stuff?
extern void output_passinit(void);
@ -58,6 +57,9 @@ extern void (*output_byte)(intval_t);
// returns zero if ok, nonzero if already set
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:

View File

@ -1372,6 +1372,35 @@ static enum eos po_serious(void)
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")
static enum eos po_endoffile(void)
@ -1455,8 +1484,8 @@ static struct ronode pseudo_opcode_tree[] = {
PREDEFNODE("warn", po_warn),
PREDEFNODE("error", po_error),
PREDEFNODE("serious", po_serious),
// PREDEFNODE("filestart", po_),
// PREDEFNODE("filestop", po_),
PREDEFNODE("outfilestart", po_outfilestart),
PREDEFNODE("outfilelimit", po_outfilelimit),
PREDEFNODE("eof", po_endoffile),
PREDEF_END("endoffile", po_endoffile),
// ^^^^ this marks the last element

View File

@ -9,7 +9,7 @@
#define RELEASE "0.97" // update before release FIXME
#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 HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/"
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME