mirror of
https://github.com/uffejakobsen/acme.git
synced 2025-02-07 06:31:03 +00:00
refactored !bin, !fill and !align a bit
git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@422 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
df8e52b544
commit
4d260b2826
@ -617,7 +617,7 @@ void throw_finalpass_warning(const char msg[])
|
|||||||
throw_warning(msg);
|
throw_warning(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// throw "macro twice" error (FIXME - also use for "symbol twice"!)
|
// throw "macro twice"/"symbol twice" error
|
||||||
// first output error as "error", then location of initial definition as "info"
|
// first output error as "error", then location of initial definition as "info"
|
||||||
void throw_redef_error(const char error_msg[], struct location *old_def, const char info_msg[])
|
void throw_redef_error(const char error_msg[], struct location *old_def, const char info_msg[])
|
||||||
{
|
{
|
||||||
|
@ -238,7 +238,7 @@ extern void throw_pass1_warning(const char msg[]);
|
|||||||
// final pass because values might be undefined earlier!)
|
// final pass because values might be undefined earlier!)
|
||||||
extern void throw_finalpass_warning(const char msg[]);
|
extern void throw_finalpass_warning(const char msg[]);
|
||||||
|
|
||||||
// throw "macro twice" error (FIXME - also use for "symbol twice"!)
|
// throw "macro twice"/"symbol twice" error
|
||||||
// first output error as "error", then location of initial definition as "info"
|
// first output error as "error", then location of initial definition as "info"
|
||||||
extern void throw_redef_error(const char error_msg[], struct location *old_def, const char info_msg[]);
|
extern void throw_redef_error(const char error_msg[], struct location *old_def, const char info_msg[]);
|
||||||
|
|
||||||
|
@ -923,11 +923,10 @@ int input_read_input_filename(struct filespecflags *flags)
|
|||||||
return 1; // unterminated or escaping error
|
return 1; // unterminated or escaping error
|
||||||
|
|
||||||
GetByte(); // eat terminator
|
GetByte(); // eat terminator
|
||||||
// new algo:
|
// new algo: (FIXME)
|
||||||
// it should be possible to construct the name of input file from symbols, so
|
// it should be possible to construct the name of input file from symbols, so
|
||||||
// build environments can define a name at one place and use it at another.
|
// build environments can define a name at one place and use it at another.
|
||||||
// FIXME - use expression parser to read filename string!
|
// FIXME - use expression parser to read filename string!
|
||||||
// see lines 416 and 1317 in pseudoopcodes.c for two more possible callers!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check length, remember abs/rel, unescape, terminate, do platform conversion
|
// check length, remember abs/rel, unescape, terminate, do platform conversion
|
||||||
|
@ -24,6 +24,15 @@
|
|||||||
|
|
||||||
|
|
||||||
// TODO - make new, keyword-based argument parser for !bin, !fill and !align
|
// TODO - make new, keyword-based argument parser for !bin, !fill and !align
|
||||||
|
// helper function to support switching from positional arguments to keyword arguments
|
||||||
|
static boolean line_uses_keyword_arguments(void)
|
||||||
|
{
|
||||||
|
// to be on the safe side, return FALSE if dialect < 0.98!
|
||||||
|
// read line to buffer, check if it begins with '[a-zA-Z]+='
|
||||||
|
// change input to RAM, return result
|
||||||
|
// ...and the caller needs to pass us some struct so it can change input back later on!
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// different ways to handle end-of-statement:
|
// different ways to handle end-of-statement:
|
||||||
@ -525,19 +534,54 @@ static enum eos po_scrxor(void)
|
|||||||
return SKIP_REMAINDER;
|
return SKIP_REMAINDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// "backend" function for "!binary"
|
||||||
|
static void include_file(FILE *stream, intval_t size, intval_t offset)
|
||||||
|
{
|
||||||
|
int byte,
|
||||||
|
amount;
|
||||||
|
|
||||||
|
// check whether including is a waste of time
|
||||||
|
// FIXME - future changes ("several-projects-at-once")
|
||||||
|
// may be incompatible with this!
|
||||||
|
if ((size >= 0) && (!pass.flags.generate_output)) {
|
||||||
|
output_skip(size); // really including is useless anyway
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// really insert file
|
||||||
|
fseek(stream, offset, SEEK_SET); // set read pointer
|
||||||
|
// read "size" bytes. if size is "NO_VALUE_GIVEN" (which is -1),
|
||||||
|
// decrementing it won't give zero, so we'll read until EOF,
|
||||||
|
// which is exactly what we want if no size was given:
|
||||||
|
while (size != 0) {
|
||||||
|
byte = getc(stream);
|
||||||
|
if (byte == EOF)
|
||||||
|
break;
|
||||||
|
output_byte(byte);
|
||||||
|
--size;
|
||||||
|
}
|
||||||
|
// if more should have been read, warn and add padding
|
||||||
|
if (size > 0) {
|
||||||
|
throw_warning("Padding with zeroes.");
|
||||||
|
do {
|
||||||
|
output_byte(0);
|
||||||
|
} while (--size);
|
||||||
|
}
|
||||||
|
// if verbose, produce some output
|
||||||
|
if (config.process_verbosity >= 2) {
|
||||||
|
amount = output_get_statement_size();
|
||||||
|
printf("Loaded %d (0x%04x) bytes from file offset %d (0x%04x).\n",
|
||||||
|
amount, amount, offset, offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
// include binary file ("!binary" pseudo opcode)
|
// include binary file ("!binary" pseudo opcode)
|
||||||
// FIXME - split this into "parser" and "worker" fn and move worker fn somewhere else.
|
|
||||||
static enum eos po_binary(void)
|
static enum eos po_binary(void)
|
||||||
{
|
{
|
||||||
struct filespecflags flags;
|
struct filespecflags flags;
|
||||||
FILE *stream;
|
FILE *stream;
|
||||||
int byte;
|
struct number arg;
|
||||||
struct number size,
|
intval_t size = NO_VALUE_GIVEN, // means "until EOF"
|
||||||
skip;
|
skip = 0;
|
||||||
int amount;
|
|
||||||
|
|
||||||
size.val.intval = -1; // means "not given" => "until EOF"
|
|
||||||
skip.val.intval = 0;
|
|
||||||
|
|
||||||
// read file name and convert from UNIX style to platform style
|
// read file name and convert from UNIX style to platform style
|
||||||
if (input_read_input_filename(&flags))
|
if (input_read_input_filename(&flags))
|
||||||
@ -548,55 +592,36 @@ static enum eos po_binary(void)
|
|||||||
if (stream == NULL)
|
if (stream == NULL)
|
||||||
return SKIP_REMAINDER;
|
return SKIP_REMAINDER;
|
||||||
|
|
||||||
// read optional arguments
|
// any more arguments?
|
||||||
if (parser_accept_comma()) {
|
if (parser_accept_comma()) {
|
||||||
// any size given?
|
if (line_uses_keyword_arguments()) {
|
||||||
if ((GotByte != ',') && (GotByte != CHAR_EOS)) {
|
// read keyword arguments
|
||||||
// then parse it
|
// TODO!
|
||||||
ALU_defined_int(&size);
|
BUG("KeywordArgsNotYet", 0);
|
||||||
if (size.val.intval < 0)
|
} else {
|
||||||
throw_serious_error(exception_negative_size);
|
// read old-style, positional arguments:
|
||||||
}
|
if ((GotByte != ',') && (GotByte != CHAR_EOS)) {
|
||||||
// more?
|
// first arg is "size"
|
||||||
if (parser_accept_comma()) {
|
ALU_defined_int(&arg);
|
||||||
// any skip given?
|
size = arg.val.intval;
|
||||||
if (GotByte != CHAR_EOS) {
|
// CAUTION: do not move this check elsewhere,
|
||||||
// then parse it
|
// because the default value -1 is ok!
|
||||||
ALU_defined_int(&skip);
|
if (size < 0)
|
||||||
|
throw_serious_error(exception_negative_size);
|
||||||
|
}
|
||||||
|
// more?
|
||||||
|
if (parser_accept_comma()) {
|
||||||
|
// second arg is "skip"
|
||||||
|
if (GotByte != CHAR_EOS) {
|
||||||
|
// then parse it
|
||||||
|
ALU_defined_int(&arg);
|
||||||
|
skip = arg.val.intval;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// check whether including is a waste of time
|
// FIXME - add check for "skip" and complain if negative!
|
||||||
// FIXME - future changes ("several-projects-at-once")
|
include_file(stream, size, skip);
|
||||||
// may be incompatible with this!
|
|
||||||
if ((size.val.intval >= 0) && (!pass.flags.generate_output)) {
|
|
||||||
output_skip(size.val.intval); // really including is useless anyway
|
|
||||||
} else {
|
|
||||||
// really insert file
|
|
||||||
fseek(stream, skip.val.intval, SEEK_SET); // set read pointer
|
|
||||||
// if "size" non-negative, read "size" bytes.
|
|
||||||
// otherwise, read until EOF.
|
|
||||||
while (size.val.intval != 0) {
|
|
||||||
byte = getc(stream);
|
|
||||||
if (byte == EOF)
|
|
||||||
break;
|
|
||||||
output_byte(byte);
|
|
||||||
--size.val.intval;
|
|
||||||
}
|
|
||||||
// if more should have been read, warn and add padding
|
|
||||||
if (size.val.intval > 0) {
|
|
||||||
throw_warning("Padding with zeroes.");
|
|
||||||
do {
|
|
||||||
output_byte(0);
|
|
||||||
} while (--size.val.intval);
|
|
||||||
}
|
|
||||||
// if verbose, produce some output
|
|
||||||
if (config.process_verbosity >= 2) {
|
|
||||||
amount = output_get_statement_size();
|
|
||||||
printf("Loaded %d (0x%04x) bytes from file offset %d (0x%04x).\n",
|
|
||||||
amount, amount, skip.val.intval, skip.val.intval);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(stream);
|
fclose(stream);
|
||||||
return ENSURE_EOS;
|
return ENSURE_EOS;
|
||||||
}
|
}
|
||||||
@ -608,9 +633,17 @@ static enum eos po_fill(void)
|
|||||||
struct number sizeresult;
|
struct number sizeresult;
|
||||||
intval_t fill = FILLVALUE_FILL;
|
intval_t fill = FILLVALUE_FILL;
|
||||||
|
|
||||||
ALU_defined_int(&sizeresult); // FIXME - forbid addresses!
|
if (line_uses_keyword_arguments()) {
|
||||||
if (parser_accept_comma())
|
// read keyword arguments
|
||||||
ALU_any_int(&fill); // FIXME - forbid addresses!
|
// TODO!
|
||||||
|
BUG("KeywordArgsNotYet", 1);
|
||||||
|
} else {
|
||||||
|
// read old-style, positional arguments:
|
||||||
|
ALU_defined_int(&sizeresult); // FIXME - forbid addresses!
|
||||||
|
if (parser_accept_comma())
|
||||||
|
ALU_any_int(&fill); // FIXME - forbid addresses!
|
||||||
|
}
|
||||||
|
|
||||||
while (sizeresult.val.intval--)
|
while (sizeresult.val.intval--)
|
||||||
output_8(fill);
|
output_8(fill);
|
||||||
return ENSURE_EOS;
|
return ENSURE_EOS;
|
||||||
@ -633,25 +666,34 @@ static enum eos po_skip(void) // now GotByte = illegal char
|
|||||||
|
|
||||||
|
|
||||||
// insert byte until PC fits condition
|
// insert byte until PC fits condition
|
||||||
|
// TODO:
|
||||||
|
// now: "!align ANDVALUE, EQUALVALUE [,FILLVALUE]"
|
||||||
|
// in future: use keyword arguments so "!align fillvalue=17, blocksize=64" is
|
||||||
|
// possible (where blocksize must be a power of two)
|
||||||
static enum eos po_align(void)
|
static enum eos po_align(void)
|
||||||
{
|
{
|
||||||
struct number andresult,
|
struct number arg;
|
||||||
equalresult;
|
intval_t andresult,
|
||||||
intval_t fill;
|
equalresult,
|
||||||
|
fill = cpu_current_type->default_align_value;
|
||||||
struct number pc;
|
struct number pc;
|
||||||
|
|
||||||
// TODO:
|
if (line_uses_keyword_arguments()) {
|
||||||
// now: "!align ANDVALUE, EQUALVALUE [,FILLVALUE]"
|
// read keyword arguments
|
||||||
// in future: "!align BLOCKSIZE" where block size must be a power of two
|
// TODO!
|
||||||
ALU_defined_int(&andresult); // FIXME - forbid addresses!
|
BUG("KeywordArgsNotYet", 2);
|
||||||
if (parser_expect(',')) {
|
} else {
|
||||||
// fn already does everything for us
|
// read old-style, positional arguments:
|
||||||
|
ALU_defined_int(&arg); // FIXME - forbid addresses!
|
||||||
|
andresult = arg.val.intval;
|
||||||
|
if (parser_expect(',')) {
|
||||||
|
// fn already does everything for us
|
||||||
|
}
|
||||||
|
ALU_defined_int(&arg); // ...allow addresses (unlikely, but possible)
|
||||||
|
equalresult = arg.val.intval;
|
||||||
|
if (parser_accept_comma())
|
||||||
|
ALU_any_int(&fill);
|
||||||
}
|
}
|
||||||
ALU_defined_int(&equalresult); // ...allow addresses (unlikely, but possible)
|
|
||||||
if (parser_accept_comma())
|
|
||||||
ALU_any_int(&fill);
|
|
||||||
else
|
|
||||||
fill = cpu_current_type->default_align_value;
|
|
||||||
|
|
||||||
// make sure PC is defined
|
// make sure PC is defined
|
||||||
programcounter_read_pc(&pc);
|
programcounter_read_pc(&pc);
|
||||||
@ -660,7 +702,7 @@ static enum eos po_align(void)
|
|||||||
return SKIP_REMAINDER;
|
return SKIP_REMAINDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((pc.val.intval++ & andresult.val.intval) != equalresult.val.intval)
|
while ((pc.val.intval++ & andresult) != equalresult)
|
||||||
output_8(fill);
|
output_8(fill);
|
||||||
return ENSURE_EOS;
|
return ENSURE_EOS;
|
||||||
}
|
}
|
||||||
|
@ -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 "24 Aug" // update before release FIXME
|
#define CHANGE_DATE "25 Aug" // 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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user