mirror of
https://github.com/uffejakobsen/acme.git
synced 2024-11-22 03:30:46 +00:00
moved code around, no change in functionality
git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@370 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
1e62973f99
commit
5a504b4ff3
@ -32,8 +32,7 @@ enum eos {
|
||||
};
|
||||
|
||||
// constants
|
||||
static const char exception_unknown_pseudo_opcode[] = "Unknown pseudo opcode.";
|
||||
static const char exception_missing_equals[] = "Missing '=' character.";
|
||||
static const char exception_missing_equals[] = "Missing '=' character.";
|
||||
|
||||
|
||||
// helper function, just for old, deprecated, obsolete, stupid "realpc":
|
||||
@ -44,86 +43,7 @@ static void end_all_pseudopc(void)
|
||||
}
|
||||
|
||||
|
||||
// local prototype because "*=" might fake a "!outfilestart":
|
||||
static enum eos po_outfilestart(void);
|
||||
|
||||
// this is not really a pseudo opcode, but similar enough to be put here:
|
||||
// called when "*= EXPRESSION" is parsed, to set the program counter
|
||||
void notreallypo_setpc(void) // GotByte is '*'
|
||||
{
|
||||
bits segment_flags = 0;
|
||||
boolean do_outfilestart = FALSE;
|
||||
struct number intresult;
|
||||
|
||||
// next non-space must be '='
|
||||
NEXTANDSKIPSPACE();
|
||||
if (GotByte != '=') {
|
||||
Throw_error(exception_missing_equals);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
GetByte();
|
||||
ALU_defined_int(&intresult); // read new address
|
||||
// check for modifiers
|
||||
while (input_accept_comma()) {
|
||||
// parse modifier. if no keyword given, give up
|
||||
if (input_read_and_lower_keyword() == 0)
|
||||
goto fail;
|
||||
|
||||
if (strcmp(GlobalDynaBuf->buffer, "overlay") == 0) {
|
||||
segment_flags |= SEGMENT_FLAG_OVERLAY;
|
||||
} else if (strcmp(GlobalDynaBuf->buffer, "invisible") == 0) {
|
||||
segment_flags |= SEGMENT_FLAG_INVISIBLE;
|
||||
} else if (strcmp(GlobalDynaBuf->buffer, "outfilestart") == 0) {
|
||||
do_outfilestart = TRUE;
|
||||
/*TODO } else if (strcmp(GlobalDynaBuf->buffer, "limit") == 0) {
|
||||
skip '='
|
||||
read memory limit
|
||||
} else if (strcmp(GlobalDynaBuf->buffer, "stay" or "same" or something like that) == 0) {
|
||||
mutually exclusive with all other arguments!
|
||||
this would mean to keep all previous segment data,
|
||||
so it could be used with "*=*-5" or "*=*+3"
|
||||
} else if (strcmp(GlobalDynaBuf->buffer, "name") == 0) {
|
||||
skip '='
|
||||
read segment name (quoted string!) */
|
||||
} else {
|
||||
Throw_error("Unknown \"*=\" segment modifier.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
// before actually setting pc,
|
||||
// support stupidly bad, old, ancient, deprecated, obsolete behaviour:
|
||||
if (pseudopc_isactive()) {
|
||||
if (config.dialect >= V0_94_8__DISABLED_OBSOLETE) {
|
||||
// current behaviour:
|
||||
// setting pc does not disable pseudopc
|
||||
} else if (config.dialect >= V0_93__SHORTER_SETPC_WARNING) {
|
||||
Throw_warning("Offset assembly still active at end of segment.");
|
||||
end_all_pseudopc(); // warning did not say it would
|
||||
// disable pseudopc, but still did. nevertheless, there
|
||||
// is something different to older versions: when the
|
||||
// closing '}' or !realpc is encountered, _really_ weird
|
||||
// stuff happens! i see no reason to try to mimic that.
|
||||
} else {
|
||||
// prior to 0.93, setting pc disabled pseudopc with a warning:
|
||||
Throw_warning("Offset assembly still active at end of segment. Switched it off.");
|
||||
end_all_pseudopc();
|
||||
}
|
||||
}
|
||||
|
||||
vcpu_set_pc(intresult.val.intval, segment_flags);
|
||||
|
||||
// if wanted, perform "!outfilestart":
|
||||
if (do_outfilestart)
|
||||
po_outfilestart();
|
||||
|
||||
input_ensure_EOS();
|
||||
return;
|
||||
|
||||
fail:
|
||||
input_skip_remainder();
|
||||
}
|
||||
// "configuration" pseudo opcodes (can be overridden by cli arguments):
|
||||
|
||||
|
||||
// define default value for empty memory ("!initmem" pseudo opcode)
|
||||
@ -131,7 +51,7 @@ static enum eos po_initmem(void)
|
||||
{
|
||||
struct number intresult;
|
||||
|
||||
// ignore in all passes but in first
|
||||
// ignore in later passes
|
||||
if (pass.number != 1)
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
@ -139,39 +59,21 @@ static enum eos po_initmem(void)
|
||||
ALU_defined_int(&intresult);
|
||||
if ((intresult.val.intval > 255) || (intresult.val.intval < -128))
|
||||
Throw_error(exception_number_out_of_8b_range);
|
||||
// TODO - move "Memory already initialised." logic from output.c
|
||||
// to this place.
|
||||
// TODO - increment pass.changed_count to enforce another pass.
|
||||
if (output_setdefault(intresult.val.intval & 0xff))
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
||||
|
||||
// change output "encryption" ("!xor" pseudo opcode)
|
||||
// (allows for block, so must be reentrant)
|
||||
static enum eos po_xor(void)
|
||||
{
|
||||
char old_value;
|
||||
intval_t change;
|
||||
|
||||
old_value = output_get_xor();
|
||||
ALU_any_int(&change);
|
||||
if ((change > 255) || (change < -128)) {
|
||||
Throw_error(exception_number_out_of_8b_range);
|
||||
change = 0;
|
||||
}
|
||||
output_set_xor(old_value ^ change);
|
||||
// if there's a block, parse that and then restore old value!
|
||||
if (parse_optional_block())
|
||||
output_set_xor(old_value);
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
||||
|
||||
// select output file name and format ("!to" pseudo opcode)
|
||||
static enum eos po_to(void)
|
||||
{
|
||||
enum outfile_format format;
|
||||
|
||||
// only process this pseudo opcode in first pass
|
||||
// ignore in later passes
|
||||
if (pass.number != 1)
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
@ -219,6 +121,90 @@ static enum eos po_to(void)
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
||||
// set file name for symbol list
|
||||
static enum eos po_symbollist(void)
|
||||
{
|
||||
// ignore in later passes
|
||||
if (pass.number != 1)
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
// cli arg and earlier calls have priority
|
||||
if (config.symbollist_filename) {
|
||||
Throw_warning("Symbol list file name already chosen.");
|
||||
return SKIP_REMAINDER;
|
||||
}
|
||||
|
||||
// read filename to global dynamic buffer
|
||||
// if no file name given, exit (complaining will have been done)
|
||||
if (input_read_output_filename())
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
// get malloc'd copy of filename
|
||||
config.symbollist_filename = dynabuf_get_copy(GlobalDynaBuf);
|
||||
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
||||
|
||||
// set start and end (can also be overwritten by cli args):
|
||||
|
||||
|
||||
// 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)) {
|
||||
if (pass.number == 1)
|
||||
Throw_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)) {
|
||||
if (pass.number == 1)
|
||||
Throw_warning("End of output file already chosen.");
|
||||
} else {
|
||||
last_pass_number = pass.number;
|
||||
outbuf_set_outfile_limit();
|
||||
}
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
||||
|
||||
// "real" pseudo opcodes:
|
||||
|
||||
|
||||
// change output "encryption" ("!xor" pseudo opcode)
|
||||
// (allows for block, so must be reentrant)
|
||||
static enum eos po_xor(void)
|
||||
{
|
||||
char old_value;
|
||||
intval_t change;
|
||||
|
||||
old_value = output_get_xor();
|
||||
ALU_any_int(&change);
|
||||
if ((change > 255) || (change < -128)) {
|
||||
Throw_error(exception_number_out_of_8b_range);
|
||||
change = 0;
|
||||
}
|
||||
output_set_xor(old_value ^ change);
|
||||
// if there's a block, parse that and then restore old value!
|
||||
if (parse_optional_block())
|
||||
output_set_xor(old_value);
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
||||
|
||||
// helper function for !8, !16, !24 and !32 pseudo opcodes
|
||||
static enum eos iterate(void (*fn)(intval_t))
|
||||
@ -850,32 +836,6 @@ static enum eos po_set(void) // now GotByte = illegal char
|
||||
}
|
||||
|
||||
|
||||
// set file name for symbol list
|
||||
static enum eos po_symbollist(void)
|
||||
{
|
||||
// only process this pseudo opcode in first pass
|
||||
if (pass.number != 1)
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
// cli arg and earlier calls supersede this call
|
||||
if (config.symbollist_filename) {
|
||||
Throw_warning("Symbol list file name already chosen.");
|
||||
return SKIP_REMAINDER;
|
||||
}
|
||||
|
||||
// read filename to global dynamic buffer
|
||||
// if no file name given, exit (complaining will have been done)
|
||||
if (input_read_output_filename())
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
// get malloc'd copy of filename
|
||||
config.symbollist_filename = dynabuf_get_copy(GlobalDynaBuf);
|
||||
|
||||
// ensure there's no garbage at end of line
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
||||
|
||||
// switch to new zone ("!zone" or "!zn"). has to be re-entrant.
|
||||
// (allows for block, so must be reentrant)
|
||||
static enum eos po_zone(void)
|
||||
@ -1445,36 +1405,6 @@ 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)) {
|
||||
if (pass.number == 1)
|
||||
Throw_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)) {
|
||||
if (pass.number == 1)
|
||||
Throw_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")
|
||||
@ -1490,8 +1420,12 @@ static enum eos po_endoffile(void)
|
||||
static struct ronode pseudo_opcode_tree[] = {
|
||||
PREDEF_START,
|
||||
PREDEFNODE("initmem", po_initmem),
|
||||
PREDEFNODE("xor", po_xor),
|
||||
PREDEFNODE("to", po_to),
|
||||
PREDEFNODE("sl", po_symbollist),
|
||||
PREDEFNODE("symbollist", po_symbollist),
|
||||
PREDEFNODE("outfilestart", po_outfilestart),
|
||||
PREDEFNODE("outfilelimit", po_outfilelimit),
|
||||
PREDEFNODE("xor", po_xor),
|
||||
PREDEFNODE("by", po_byte),
|
||||
PREDEFNODE("byte", po_byte),
|
||||
PREDEFNODE("8", po_byte),
|
||||
@ -1534,8 +1468,6 @@ static struct ronode pseudo_opcode_tree[] = {
|
||||
PREDEFNODE("rs", po_rs),
|
||||
// PREDEFNODE("enum", po_enum),
|
||||
PREDEFNODE("set", po_set),
|
||||
PREDEFNODE("sl", po_symbollist),
|
||||
PREDEFNODE("symbollist", po_symbollist),
|
||||
PREDEFNODE("zn", po_zone),
|
||||
PREDEFNODE("zone", po_zone),
|
||||
PREDEFNODE("sz", po_subzone), // obsolete
|
||||
@ -1559,8 +1491,6 @@ static struct ronode pseudo_opcode_tree[] = {
|
||||
PREDEFNODE("warn", po_warn),
|
||||
PREDEFNODE("error", po_error),
|
||||
PREDEFNODE("serious", po_serious),
|
||||
PREDEFNODE("outfilestart", po_outfilestart),
|
||||
PREDEFNODE("outfilelimit", po_outfilelimit),
|
||||
PREDEFNODE("eof", po_endoffile),
|
||||
PREDEF_END("endoffile", po_endoffile),
|
||||
// ^^^^ this marks the last element
|
||||
@ -1585,7 +1515,7 @@ void pseudoopcode_parse(void) // now GotByte = '!' (or '.' in case of --fullstop
|
||||
// call function
|
||||
then = fn();
|
||||
} else {
|
||||
Throw_error(exception_unknown_pseudo_opcode);
|
||||
Throw_error("Unknown pseudo opcode.");
|
||||
}
|
||||
}
|
||||
if (then == SKIP_REMAINDER)
|
||||
@ -1595,3 +1525,82 @@ void pseudoopcode_parse(void) // now GotByte = '!' (or '.' in case of --fullstop
|
||||
// the other two possibilities (PARSE_REMAINDER and AT_EOS_ANYWAY)
|
||||
// will lead to the remainder of the line being parsed by the mainloop.
|
||||
}
|
||||
|
||||
|
||||
// this is not really a pseudo opcode, but similar enough to be put here:
|
||||
// called when "*= EXPRESSION" is parsed, to set the program counter
|
||||
void notreallypo_setpc(void) // GotByte is '*'
|
||||
{
|
||||
bits segment_flags = 0;
|
||||
boolean do_outfilestart = FALSE;
|
||||
struct number intresult;
|
||||
|
||||
// next non-space must be '='
|
||||
NEXTANDSKIPSPACE();
|
||||
if (GotByte != '=') {
|
||||
Throw_error(exception_missing_equals);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
GetByte();
|
||||
ALU_defined_int(&intresult); // read new address
|
||||
// check for modifiers
|
||||
while (input_accept_comma()) {
|
||||
// parse modifier. if no keyword given, give up
|
||||
if (input_read_and_lower_keyword() == 0)
|
||||
goto fail;
|
||||
|
||||
if (strcmp(GlobalDynaBuf->buffer, "overlay") == 0) {
|
||||
segment_flags |= SEGMENT_FLAG_OVERLAY;
|
||||
} else if (strcmp(GlobalDynaBuf->buffer, "invisible") == 0) {
|
||||
segment_flags |= SEGMENT_FLAG_INVISIBLE;
|
||||
} else if (strcmp(GlobalDynaBuf->buffer, "outfilestart") == 0) {
|
||||
do_outfilestart = TRUE;
|
||||
/*TODO } else if (strcmp(GlobalDynaBuf->buffer, "limit") == 0) {
|
||||
skip '='
|
||||
read memory limit
|
||||
} else if (strcmp(GlobalDynaBuf->buffer, "stay" or "same" or something like that) == 0) {
|
||||
mutually exclusive with all other arguments!
|
||||
this would mean to keep all previous segment data,
|
||||
so it could be used with "*=*-5" or "*=*+3"
|
||||
} else if (strcmp(GlobalDynaBuf->buffer, "name") == 0) {
|
||||
skip '='
|
||||
read segment name (quoted string!) */
|
||||
} else {
|
||||
Throw_error("Unknown \"*=\" segment modifier.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
// before actually setting pc,
|
||||
// support stupidly bad, old, ancient, deprecated, obsolete behaviour:
|
||||
if (pseudopc_isactive()) {
|
||||
if (config.dialect >= V0_94_8__DISABLED_OBSOLETE) {
|
||||
// current behaviour:
|
||||
// setting pc does not disable pseudopc
|
||||
} else if (config.dialect >= V0_93__SHORTER_SETPC_WARNING) {
|
||||
Throw_warning("Offset assembly still active at end of segment.");
|
||||
end_all_pseudopc(); // warning did not say it would
|
||||
// disable pseudopc, but still did. nevertheless, there
|
||||
// is something different to older versions: when the
|
||||
// closing '}' or !realpc is encountered, _really_ weird
|
||||
// stuff happens! i see no reason to try to mimic that.
|
||||
} else {
|
||||
// prior to 0.93, setting pc disabled pseudopc with a warning:
|
||||
Throw_warning("Offset assembly still active at end of segment. Switched it off.");
|
||||
end_all_pseudopc();
|
||||
}
|
||||
}
|
||||
|
||||
vcpu_set_pc(intresult.val.intval, segment_flags);
|
||||
|
||||
// if wanted, perform "!outfilestart":
|
||||
if (do_outfilestart)
|
||||
po_outfilestart();
|
||||
|
||||
input_ensure_EOS();
|
||||
return;
|
||||
|
||||
fail:
|
||||
input_skip_remainder();
|
||||
}
|
||||
|
@ -7,11 +7,12 @@
|
||||
#define pseudoopcodes_H
|
||||
|
||||
|
||||
// call when "*= EXPRESSION" is parsed
|
||||
extern void notreallypo_setpc(void);
|
||||
|
||||
// parse pseudo opcode. has to be re-entrant.
|
||||
extern void pseudoopcode_parse(void);
|
||||
|
||||
// this is not really a pseudo opcode, but similar enough to be put here:
|
||||
// call when "*= EXPRESSION" is parsed
|
||||
extern void notreallypo_setpc(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#define RELEASE "0.97" // update before release FIXME
|
||||
#define CODENAME "Zem" // update before release
|
||||
#define CHANGE_DATE "12 Mar" // update before release FIXME
|
||||
#define CHANGE_DATE "13 Mar" // 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
|
||||
|
Loading…
Reference in New Issue
Block a user