more cleanup

added "outfilestart" keyword to "*="
added "file" keyword to "!convtab"


git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@339 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
marcobaye 2024-02-17 16:52:32 +00:00
parent 6c3ec454d3
commit 496fde6f1a
17 changed files with 159 additions and 184 deletions

View File

@ -28,7 +28,7 @@ cpu.o: config.h alu.h dynabuf.h global.h input.h mnemo.h output.h tree.h cpu.h c
dynabuf.o: config.h acme.h global.h input.h dynabuf.h dynabuf.c
encoding.o: config.h alu.h acme.h dynabuf.h global.h output.h input.h tree.h encoding.h encoding.c
encoding.o: encoding.h encoding.c
flow.o: config.h acme.h alu.h dynabuf.h global.h input.h mnemo.h symbol.h tree.h flow.h flow.c

View File

@ -28,7 +28,7 @@ cpu.o: config.h alu.h dynabuf.h global.h input.h mnemo.h output.h tree.h cpu.h c
dynabuf.o: config.h acme.h global.h input.h dynabuf.h dynabuf.c
encoding.o: config.h alu.h acme.h dynabuf.h global.h output.h input.h tree.h encoding.h encoding.c
encoding.o: encoding.h encoding.c
flow.o: config.h acme.h alu.h dynabuf.h global.h input.h mnemo.h symbol.h tree.h flow.h flow.c

View File

@ -31,7 +31,7 @@ cpu.o: config.h alu.h dynabuf.h global.h input.h mnemo.h output.h tree.h cpu.h c
dynabuf.o: config.h acme.h global.h input.h dynabuf.h dynabuf.c
encoding.o: config.h alu.h acme.h dynabuf.h global.h output.h input.h tree.h encoding.h encoding.c
encoding.o: encoding.h encoding.c
flow.o: config.h acme.h alu.h dynabuf.h global.h input.h mnemo.h symbol.h tree.h flow.h flow.c

View File

@ -27,7 +27,7 @@ cpu.o: config.h alu.h dynabuf.h global.h input.h mnemo.h output.h tree.h cpu.h c
dynabuf.o: config.h acme.h global.h input.h dynabuf.h dynabuf.c
encoding.o: config.h alu.h acme.h dynabuf.h global.h output.h input.h tree.h encoding.h encoding.c
encoding.o: encoding.h encoding.c
flow.o: config.h acme.h alu.h dynabuf.h global.h input.h mnemo.h symbol.h tree.h flow.h flow.c

View File

@ -80,11 +80,6 @@ static const char arg_vicelabels[] = "VICE labels filename";
// variables
static const char **toplevel_sources;
static int toplevel_src_count = 0;
static const struct cpu_type *default_cpu = NULL;
const char *symbollist_filename = NULL;
const char *vicelabels_filename = NULL;
const char *output_filename = NULL;
const char *report_filename = NULL;
// maximum recursion depth for macro calls and "!source"
signed long macro_recursions_left = MAX_NESTING;
signed long source_recursions_left = MAX_NESTING;
@ -197,25 +192,25 @@ int ACME_finalize(int exit_code)
FILE *fd;
report_close(report);
if (symbollist_filename) {
fd = fopen(symbollist_filename, FILE_WRITETEXT); // FIXME - what if filename is given via !sl in sub-dir? fix path!
if (config.symbollist_filename) {
fd = fopen(config.symbollist_filename, FILE_WRITETEXT); // FIXME - what if filename is given via !sl in sub-dir? fix path!
if (fd) {
symbols_list(fd);
fclose(fd);
PLATFORM_SETFILETYPE_TEXT(symbollist_filename);
PLATFORM_SETFILETYPE_TEXT(config.symbollist_filename);
} else {
fprintf(stderr, "Error: Cannot open symbol list file \"%s\".\n", symbollist_filename);
fprintf(stderr, "Error: Cannot open symbol list file \"%s\".\n", config.symbollist_filename);
exit_code = EXIT_FAILURE;
}
}
if (vicelabels_filename) {
fd = fopen(vicelabels_filename, FILE_WRITETEXT);
if (config.vicelabels_filename) {
fd = fopen(config.vicelabels_filename, FILE_WRITETEXT);
if (fd) {
symbols_vicelabels(fd);
fclose(fd);
PLATFORM_SETFILETYPE_TEXT(vicelabels_filename);
PLATFORM_SETFILETYPE_TEXT(config.vicelabels_filename);
} else {
fprintf(stderr, "Error: Cannot open VICE label dump file \"%s\".\n", vicelabels_filename);
fprintf(stderr, "Error: Cannot open VICE label dump file \"%s\".\n", config.vicelabels_filename);
exit_code = EXIT_FAILURE;
}
}
@ -229,14 +224,13 @@ static void save_output_file(void)
FILE *fd;
// if no output file chosen, tell user and do nothing
if (output_filename == NULL) {
if (config.output_filename == NULL) {
fputs("No output file specified (use the \"-o\" option or the \"!to\" pseudo opcode).\n", stderr);
return;
}
fd = fopen(output_filename, FILE_WRITEBINARY); // FIXME - what if filename is given via !to in sub-dir? fix path!
fd = fopen(config.output_filename, FILE_WRITEBINARY); // FIXME - what if filename is given via !to in sub-dir? fix path!
if (fd == NULL) {
fprintf(stderr, "Error: Cannot open output file \"%s\".\n",
output_filename);
fprintf(stderr, "Error: Cannot open output file \"%s\".\n", config.output_filename);
return;
}
output_save_file(fd);
@ -253,7 +247,7 @@ static void perform_pass(void)
++pass.number;
// call modules' "pass init" functions
output_passinit(); // disable output, PC undefined
cputype_passinit(default_cpu); // set default cpu type
cputype_passinit(config.default_cpu); // set default cpu type
// if start address was given on command line, use it:
if (config.initial_pc != NO_VALUE_GIVEN)
vcpu_set_pc(config.initial_pc, 0); // 0 -> no segment flags
@ -312,10 +306,10 @@ static boolean do_actual_work(void)
if (pass.undefined_count == 0) { // FIXME - use pass.needvalue_count instead!
// if listing report is wanted and there were no errors,
// do another pass to generate listing report
if (report_filename) {
if (config.report_filename) {
if (config.process_verbosity > 1)
puts("Extra pass to generate listing report.");
if (report_open(report, report_filename) == 0) {
if (report_open(report, config.report_filename) == 0) {
perform_pass();
report_close(report);
}
@ -370,7 +364,7 @@ static void set_starting_cpu(const char cpu_name[])
keyword_to_dynabuf(cpu_name);
new_cpu_type = cputype_find();
if (new_cpu_type) {
default_cpu = new_cpu_type;
config.default_cpu = new_cpu_type;
return; // ok
}
fputs("Error: Unknown CPU type.\n", stderr);
@ -520,15 +514,15 @@ static const char *long_option(const char *string)
else if (strcmp(string, OPTION_FORMAT) == 0)
set_output_format(cliargs_get_next()); // NULL is ok (handled like unknown)
else if (strcmp(string, OPTION_OUTFILE) == 0)
output_filename = cliargs_safe_get_next(name_outfile);
config.output_filename = cliargs_safe_get_next(name_outfile);
else if (strcmp(string, OPTION_LABELDUMP) == 0) // old
symbollist_filename = cliargs_safe_get_next(arg_symbollist);
config.symbollist_filename = cliargs_safe_get_next(arg_symbollist);
else if (strcmp(string, OPTION_SYMBOLLIST) == 0) // new
symbollist_filename = cliargs_safe_get_next(arg_symbollist);
config.symbollist_filename = cliargs_safe_get_next(arg_symbollist);
else if (strcmp(string, OPTION_VICELABELS) == 0)
vicelabels_filename = cliargs_safe_get_next(arg_vicelabels);
config.vicelabels_filename = cliargs_safe_get_next(arg_vicelabels);
else if (strcmp(string, OPTION_REPORT) == 0)
report_filename = cliargs_safe_get_next(arg_reportfile);
config.report_filename = cliargs_safe_get_next(arg_reportfile);
else if (strcmp(string, OPTION_SETPC) == 0)
config.initial_pc = string_to_nonneg_number(cliargs_safe_get_next("program counter"));
else if (strcmp(string, OPTION_FROM_TO) == 0) {
@ -596,13 +590,13 @@ static char short_option(const char *argument)
includepaths_add(cliargs_safe_get_next("include path"));
goto done;
case 'l': // "-l" selects symbol list filename
symbollist_filename = cliargs_safe_get_next(arg_symbollist);
config.symbollist_filename = cliargs_safe_get_next(arg_symbollist);
break;
case 'o': // "-o" selects output filename
output_filename = cliargs_safe_get_next(name_outfile);
config.output_filename = cliargs_safe_get_next(name_outfile);
break;
case 'r': // "-r" selects report filename
report_filename = cliargs_safe_get_next(arg_reportfile);
config.report_filename = cliargs_safe_get_next(arg_reportfile);
break;
case 'v': // "-v" changes verbosity
++config.process_verbosity;

View File

@ -10,10 +10,6 @@
#include "config.h"
// Variables
extern const char *symbollist_filename;
extern const char *output_filename; // TODO - put in "part" struct
extern const char *report_filename; // TODO - put in "part" struct
// maximum recursion depth for macro calls and "!source"
extern signed long macro_recursions_left;
extern signed long source_recursions_left;

View File

@ -70,6 +70,8 @@ static struct cpu_type cpu_type_m65 = {
// variables
boolean cpu_a_is_long = FALSE;
boolean cpu_xy_are_long = FALSE;
// predefined stuff
static struct ronode cputype_tree[] = {
PREDEF_START,
@ -121,6 +123,6 @@ void cputype_passinit(const struct cpu_type *cpu_type)
{
// handle cpu type (default is 6502)
CPU_state.type = cpu_type ? cpu_type : &cpu_type_6502;
CPU_state.a_is_long = FALSE; // short accu
CPU_state.xy_are_long = FALSE; // short index regs
cpu_a_is_long = FALSE; // short accu
cpu_xy_are_long = FALSE; // short index regs
}

View File

@ -25,6 +25,10 @@ struct cpu_type {
#define CPUFLAG_DECIMALSUBTRACTBUGGY (1u << 4) // warn if "sed" is assembled
#define CPUFLAG_WARN_ABOUT_FF_PTR (1u << 5) // warn if MNEMO($ff) is assembled
// variables
extern boolean cpu_a_is_long;
extern boolean cpu_xy_are_long;
// if cpu type and value match, set register length variable to value.
// if cpu type and value don't match, complain instead.
extern void vcpu_check_and_set_reg_length(boolean *var, boolean make_long);

View File

@ -4,15 +4,6 @@
//
// Character encoding stuff
#include "encoding.h"
#include <stdio.h>
#include <string.h>
#include "alu.h"
#include "acme.h"
#include "dynabuf.h"
#include "global.h"
#include "output.h"
#include "input.h"
#include "tree.h"
// struct definition
@ -82,17 +73,6 @@ const struct encoder encoder_file = {
};
// keywords for "!convtab" pseudo opcode
static struct ronode encoder_tree[] = {
PREDEF_START,
//no! PREDEFNODE("file", &encoder_file), "!ct file" is not needed; just use {} after initial loading of table!
PREDEFNODE("pet", &encoder_pet),
PREDEFNODE("raw", &encoder_raw),
PREDEF_END("scr", &encoder_scr),
// ^^^^ this marks the last element
};
// exported functions
@ -107,24 +87,3 @@ void encoding_passinit(void)
{
encoder_current = &encoder_raw;
}
// try to load encoding table from given file
void encoding_load_from_file(unsigned char target[256], FILE *stream)
{
if (fread(target, sizeof(char), 256, stream) != 256)
Throw_error("Conversion table incomplete.");
}
// lookup encoder held in DynaBuf and return its struct pointer (or NULL on failure)
const struct encoder *encoding_find(void)
{
void *node_body;
// perform lookup
if (!tree_easy_scan(encoder_tree, &node_body, GlobalDynaBuf)) {
Throw_error("Unknown encoding.");
return NULL;
}
return node_body;
}

View File

@ -1,5 +1,5 @@
// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
// Copyright (C) 1998-2020 Marco Baye
// Copyright (C) 1998-2024 Marco Baye
// Have a look at "acme.c" for further info
//
// Character encoding stuff
@ -7,10 +7,6 @@
#define encoding_H
#include <stdio.h> // for FILE*
//struct encoder;
extern const struct encoder *encoder_current; // gets set before each pass TODO - set for each part
extern const struct encoder encoder_raw;
extern const struct encoder encoder_pet;
@ -23,12 +19,9 @@ extern unsigned char *encoding_loaded_table; // ...loaded from file
// convert character using current encoding
extern unsigned char encoding_encode_char(unsigned char byte);
// set "raw" as default encoding
extern void encoding_passinit(void);
// try to load encoding table from given file
extern void encoding_load_from_file(unsigned char target[256], FILE *stream);
// lookup encoder held in DynaBuf and return its struct pointer (or NULL on failure)
extern const struct encoder *encoding_find(void);
#endif

View File

@ -35,7 +35,7 @@ char s_untitled[] = "<untitled>"; // FIXME - this is actually const
// Exception messages during assembly
const char exception_missing_string[] = "No string given.";
const char exception_negative_size[] = "Negative size argument.";
const char exception_no_left_brace[] = "Missing '{'.";
const char exception_no_left_brace[] = "Missing '{' character.";
const char exception_no_memory_left[] = "Out of memory.";
const char exception_no_right_brace[] = "Found end-of-file instead of '}'.";
//const char exception_not_yet[] = "Sorry, feature not yet implemented.";
@ -123,6 +123,11 @@ void config_default(struct config *conf)
conf->wanted_version = VER_CURRENT; // changed by --dialect
conf->debuglevel = DEBUGLEVEL_DEBUG; // changed by --debuglevel, used by "!debug"
conf->outbuf_size = 0x10000; // 64K, "--test" changes to 16M
conf->default_cpu = NULL;
conf->symbollist_filename = NULL;
conf->vicelabels_filename = NULL;
conf->output_filename = NULL;
conf->report_filename = NULL;
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

View File

@ -87,6 +87,11 @@ struct config {
enum version wanted_version; // set by --dialect (and --test --test)
signed long debuglevel; // set by --debuglevel, used by "!debug"
signed long outbuf_size; // 64K, "--test" changes to 16M
const struct cpu_type *default_cpu;
const char *symbollist_filename;
const char *vicelabels_filename;
const char *output_filename; // TODO - put in "part" struct
const char *report_filename; // TODO - put in "part" struct
#define MEMINIT_USE_DEFAULT 256 // default value for next field if cli switch not used:
signed long mem_init_value; // set by --initmem
#define NO_VALUE_GIVEN (-1) // default value for these fields if cli switch not used:

View File

@ -889,10 +889,10 @@ static unsigned int imm_ops(bits *force_bit, unsigned char opcode, bits immediat
return ((unsigned int) opcode) << 8; // opcode in bits8.15 forces two-byte argument
case IM_ACCUMULATOR: // for 65816
long_register = CPU_state.a_is_long;
long_register = cpu_a_is_long;
break;
case IM_INDEXREGS: // for 65816
long_register = CPU_state.xy_are_long;
long_register = cpu_xy_are_long;
break;
default:
BUG("IllegalImmediateMode", immediate_mode);

View File

@ -59,6 +59,7 @@ static struct pseudopc *pseudopc_current_context; // current struct (NULL when n
// variables
static struct output default_output;
static struct output *out = &default_output;
static int statement_size; // add to PC after statement
// FIXME - make static
struct vcpu CPU_state; // current CPU state
@ -151,7 +152,7 @@ static void real_output(intval_t byte)
if (report->fd)
report_binary(byte & 0xff); // file for reporting, taking also CPU_2add
out->buffer[out->write_idx++] = (byte & 0xff) ^ out->xor;
++CPU_state.add_to_pc;
++statement_size; // count this byte
}
@ -194,7 +195,7 @@ void output_skip(int size)
out->highest_written = out->write_idx + size - 1;
// advance ptrs
out->write_idx += size;
CPU_state.add_to_pc += size;
statement_size += size; // count bytes so PC will be adjusted correctly after this
}
@ -280,21 +281,6 @@ int outputfile_prefer_cbm_format(void)
return 1;
}
// select output file ("!to" pseudo opcode)
// returns zero on success, nonzero if already set
int outputfile_set_filename(void)
{
// if output file already chosen, complain and exit
if (output_filename) {
Throw_warning("Output file already chosen.");
return 1; // failed
}
// get malloc'd copy of filename
output_filename = dynabuf_get_copy(GlobalDynaBuf);
return 0; // ok
}
// init output struct (done later)
void output_createbuffer(void)
@ -353,7 +339,7 @@ void output_save_file(FILE *fd)
// FIXME - add checks and error messages for "start is above $ffff"!)
switch (output_format) {
case OUTPUT_FORMAT_APPLE:
PLATFORM_SETFILETYPE_APPLE(output_filename);
PLATFORM_SETFILETYPE_APPLE(config.output_filename);
// output 16-bit load address in little-endian byte order
putc(start & 255, fd);
putc(start >> 8, fd);
@ -363,10 +349,10 @@ void output_save_file(FILE *fd)
break;
case OUTPUT_FORMAT_UNSPECIFIED:
case OUTPUT_FORMAT_PLAIN:
PLATFORM_SETFILETYPE_PLAIN(output_filename);
PLATFORM_SETFILETYPE_PLAIN(config.output_filename);
break;
case OUTPUT_FORMAT_CBM:
PLATFORM_SETFILETYPE_CBM(output_filename);
PLATFORM_SETFILETYPE_CBM(config.output_filename);
// output 16-bit load address in little-endian byte order
putc(start & 255, fd);
putc(start >> 8, fd);
@ -454,7 +440,7 @@ void output_passinit(void)
// FIXME - number type is "undefined", but still the intval 0 below will
// be used to calculate diff when pc is first set.
CPU_state.pc.val.intval = 0; // same as output's write_idx on pass init
CPU_state.add_to_pc = 0; // increase PC by this at end of statement
statement_size = 0; // increase PC by this at end of statement
// pseudopc stuff:
pseudopc_current_context = NULL;
@ -597,15 +583,15 @@ void vcpu_read_pc(struct number *target)
// get size of current statement (until now) - needed for "!bin" verbose output
int vcpu_get_statement_size(void)
{
return CPU_state.add_to_pc;
return statement_size;
}
// adjust program counter (called at end of each statement)
void vcpu_end_statement(void)
{
CPU_state.pc.val.intval = (CPU_state.pc.val.intval + CPU_state.add_to_pc) & (config.outbuf_size - 1);
CPU_state.add_to_pc = 0;
CPU_state.pc.val.intval = (CPU_state.pc.val.intval + statement_size) & (config.outbuf_size - 1);
statement_size = 0; // reset
}

View File

@ -23,9 +23,6 @@
struct vcpu {
const struct cpu_type *type; // current CPU type (default 6502) (FIXME - move out of struct again?)
struct number pc; // current program counter (pseudo value)
int add_to_pc; // add to PC after statement
boolean a_is_long;
boolean xy_are_long;
};
@ -71,9 +68,6 @@ extern const char outputfile_formats[]; // string to show if outputfile_set_form
// if file format isn't set, chooses CBM and returns 1.
extern int outputfile_prefer_cbm_format(void);
// try to set output file name held in DynaBuf. Returns zero on success.
extern int outputfile_set_filename(void);
// write used portion of output buffer to output file
extern void output_save_file(FILE *fd);

View File

@ -33,19 +33,24 @@ enum eos {
// constants
static const char exception_unknown_pseudo_opcode[] = "Unknown pseudo opcode.";
static const char exception_missing_equals[] = "Missing '=' character.";
// 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_syntax);
Throw_error(exception_missing_equals);
goto fail;
}
@ -61,6 +66,8 @@ void notreallypo_setpc(void) // GotByte is '*'
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
@ -68,8 +75,6 @@ void notreallypo_setpc(void) // GotByte is '*'
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, "outfilestart") == 0) {
FIXME set flag to automatically do "!outfilestart" afterward.
} else if (strcmp(GlobalDynaBuf->buffer, "name") == 0) {
skip '='
read segment name (quoted string!) */
@ -79,7 +84,11 @@ FIXME set flag to automatically do "!outfilestart" afterward.
}
}
vcpu_set_pc(intresult.val.intval, segment_flags);
// TODO - allow block syntax, so it is possible to put data "somewhere else" and then return to old position?
// if wanted, perform "!outfilestart":
if (do_outfilestart)
po_outfilestart();
input_ensure_EOS();
return;
@ -128,20 +137,26 @@ static enum eos po_xor(void)
}
// select output file and format ("!to" pseudo opcode)
// select output file name and format ("!to" pseudo opcode)
static enum eos po_to(void)
{
// only act upon this pseudo opcode in first pass
// only process this pseudo opcode in first pass
if (!FIRST_PASS)
return SKIP_REMAINDER;
// cli arg and earlier calls supersede this call
if (config.output_filename) {
Throw_warning("Output file 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;
if (outputfile_set_filename())
return SKIP_REMAINDER;
// get malloc'd copy of filename
config.output_filename = dynabuf_get_copy(GlobalDynaBuf);
// select output format
// if no comma found, use default file format
@ -308,18 +323,32 @@ static enum eos po_cbm(void)
// read encoding table from file
// (allows for block, so must be reentrant)
static enum eos user_defined_encoding(FILE *stream)
static enum eos use_encoding_from_file(void)
{
boolean uses_lib;
FILE *stream;
unsigned char local_table[256],
*buffered_table = encoding_loaded_table;
const struct encoder *buffered_encoder = encoder_current;
*buffered_table;
const struct encoder *buffered_encoder;
// read file name
if (input_read_input_filename(&uses_lib))
return SKIP_REMAINDER; // missing or unterminated file name
// read from file
stream = includepaths_open_ro(uses_lib);
if (stream) {
encoding_load_from_file(local_table, stream);
// try to load encoding table from given file
if (fread(local_table, sizeof(char), 256, stream) != 256)
Throw_error("Conversion table incomplete.");
fclose(stream);
}
encoder_current = &encoder_file; // activate new encoding
encoding_loaded_table = local_table; // activate local table
// now switch encoding
buffered_encoder = encoder_current;
encoder_current = &encoder_file;
buffered_table = encoding_loaded_table;
encoding_loaded_table = local_table;
// if there's a block, parse that and then restore old values
if (parse_optional_block()) {
encoder_current = buffered_encoder;
@ -335,19 +364,17 @@ static enum eos user_defined_encoding(FILE *stream)
// use one of the pre-defined encodings (raw, pet, scr)
// (allows for block, so must be reentrant)
static enum eos predefined_encoding(void)
static enum eos use_predefined_encoding(const struct encoder *new_encoder)
{
unsigned char local_table[256],
*buffered_table = encoding_loaded_table;
const struct encoder *buffered_encoder = encoder_current;
*buffered_table;
const struct encoder *buffered_encoder;
if (input_read_and_lower_keyword()) {
const struct encoder *new_encoder = encoding_find();
if (new_encoder)
encoder_current = new_encoder; // activate new encoder
}
encoding_loaded_table = local_table; // activate local table
// switch encoding
buffered_encoder = encoder_current;
encoder_current = new_encoder;
buffered_table = encoding_loaded_table;
encoding_loaded_table = local_table;
// if there's a block, parse that and then restore old values
if (parse_optional_block())
encoder_current = buffered_encoder;
@ -355,33 +382,42 @@ static enum eos predefined_encoding(void)
encoding_loaded_table = buffered_table;
return ENSURE_EOS;
}
// set current encoding ("!convtab" pseudo opcode)
// (allows for block, so must be reentrant)
// FIXME: current code does not allow for stuff like
// !convtab some_string_symbol + ".bin"
// because anything not starting with '<' or '"' is supposed to be a keyword.
// maybe fix this by using
// !convtab file = base + ".txt"
// in the future?
// another workaround would be:
// !convtab "" + some_string_symbol + ".bin"
// but even then input_read_input_filename needs to be fixed!
static enum eos po_convtab(void)
{
boolean uses_lib;
FILE *stream;
// is file name given old-style, without "file" keyword?
if ((GotByte == '<') || (GotByte == '"'))
return use_encoding_from_file();
if ((GotByte == '<') || (GotByte == '"')) {
// encoding table from file
if (input_read_input_filename(&uses_lib))
return SKIP_REMAINDER; // missing or unterminated file name
// expect keyword: either one of the pre-defined encodings or
// "file" with a filename argument:
if (input_read_and_lower_keyword() == 0)
return SKIP_REMAINDER; // "No string given" error has already been thrown
stream = includepaths_open_ro(uses_lib);
return user_defined_encoding(stream);
} else {
// one of the pre-defined encodings
return predefined_encoding();
// now check for known keywords:
if (strcmp(GlobalDynaBuf->buffer, "pet") == 0)
return use_predefined_encoding(&encoder_pet);
if (strcmp(GlobalDynaBuf->buffer, "raw") == 0)
return use_predefined_encoding(&encoder_raw);
if (strcmp(GlobalDynaBuf->buffer, "scr") == 0)
return use_predefined_encoding(&encoder_scr);
if (strcmp(GlobalDynaBuf->buffer, "file") == 0) {
SKIPSPACE();
if (GotByte != '=') {
Throw_error(exception_missing_equals);
return SKIP_REMAINDER;
}
GetByte(); // eat '='
return use_encoding_from_file();
}
Throw_error("Unknown encoding.");
return use_predefined_encoding(encoder_current); // keep going
}
// insert string(s)
static enum eos encode_string(const struct encoder *inner_encoder, unsigned char xor)
@ -410,7 +446,7 @@ static enum eos encode_string(const struct encoder *inner_encoder, unsigned char
GetByte();
// now convert to unescaped version
// FIXME - next call does nothing because wanted<escaping!
// FIXME - there is another block like this in line 1317!
// FIXME - there is another block like this, scan for ROOSTA!
if (input_unescape_dynabuf(0))
return SKIP_REMAINDER; // escaping error
@ -694,34 +730,34 @@ static enum eos po_cpu(void)
// (allows for block, so must be reentrant)
static enum eos set_register_length(boolean *var, boolean make_long)
{
int old_size = *var;
boolean long_before = *var;
// set new register length (or complain - whichever is more fitting)
vcpu_check_and_set_reg_length(var, make_long);
// if there's a block, parse that and then restore old value!
if (parse_optional_block())
vcpu_check_and_set_reg_length(var, old_size); // restore old length
vcpu_check_and_set_reg_length(var, long_before); // restore old length
return ENSURE_EOS;
}
// switch to long accumulator ("!al" pseudo opcode)
static enum eos po_al(void)
{
return set_register_length(&CPU_state.a_is_long, TRUE);
return set_register_length(&cpu_a_is_long, TRUE);
}
// switch to short accumulator ("!as" pseudo opcode)
static enum eos po_as(void)
{
return set_register_length(&CPU_state.a_is_long, FALSE);
return set_register_length(&cpu_a_is_long, FALSE);
}
// switch to long index registers ("!rl" pseudo opcode)
static enum eos po_rl(void)
{
return set_register_length(&CPU_state.xy_are_long, TRUE);
return set_register_length(&cpu_xy_are_long, TRUE);
}
// switch to short index registers ("!rs" pseudo opcode)
static enum eos po_rs(void)
{
return set_register_length(&CPU_state.xy_are_long, FALSE);
return set_register_length(&cpu_xy_are_long, FALSE);
}
@ -750,7 +786,7 @@ static enum eos po_set(void) // now GotByte = illegal char
force_bit = input_get_force_bit(); // skips spaces after
if (GotByte != '=') {
Throw_error(exception_syntax);
Throw_error(exception_missing_equals);
return SKIP_REMAINDER;
}
@ -772,19 +808,20 @@ static enum eos po_symbollist(void)
if (!FIRST_PASS)
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;
// if symbol list file name already set, complain and exit
if (symbollist_filename) {
Throw_warning("Symbol list file name already chosen.");
return SKIP_REMAINDER;
}
// get malloc'd copy of filename
symbollist_filename = dynabuf_get_copy(GlobalDynaBuf);
config.symbollist_filename = dynabuf_get_copy(GlobalDynaBuf);
// ensure there's no garbage at end of line
return ENSURE_EOS;
}
@ -1306,7 +1343,7 @@ static enum eos throw_src_string(enum debuglevel level, const char prefix[])
GetByte();
// now convert to unescaped version
// FIXME - next call does nothing because wanted<escaping!
// FIXME - there is another block like this in line 416!
// FIXME - there is another block like this, scan for ROOSTA!
if (input_unescape_dynabuf(0))
return SKIP_REMAINDER; // escaping error
@ -1485,7 +1522,7 @@ static struct ronode pseudo_opcode_tree[] = {
// parse a pseudo opcode. has to be re-entrant.
void pseudoopcode_parse(void) // now GotByte = "!"
void pseudoopcode_parse(void) // now GotByte = '!' (or '.' in case of --fullstop)
{
void *node_body;
enum eos (*fn)(void),

View File

@ -9,7 +9,7 @@
#define RELEASE "0.97" // update before release FIXME
#define CODENAME "Zem" // update before release
#define CHANGE_DATE "13 Feb" // update before release FIXME
#define CHANGE_DATE "14 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