diff --git a/src/acme.c b/src/acme.c index 3b2ec92..e2df97f 100644 --- a/src/acme.c +++ b/src/acme.c @@ -17,7 +17,7 @@ #define RELEASE "0.95.4" // update before release (FIXME) #define CODENAME "Fenchurch" // update before release -#define CHANGE_DATE "4 Dec" // update before release +#define CHANGE_DATE "5 Dec" // update before release #define CHANGE_YEAR "2014" // update before release //#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/" // FIXME #define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME @@ -246,7 +246,7 @@ static int perform_pass(void) // if start address was given on command line, use it: if (start_address != ILLEGAL_START_ADDRESS) vcpu_set_pc(start_address, 0); - Encoding_passinit(); // set default encoding + encoding_passinit(); // set default encoding Section_passinit(); // set initial zone (untitled) // init variables pass_undefined_count = 0; // no "NeedValue" errors yet diff --git a/src/alu.c b/src/alu.c index 7ebf1d3..b94f2eb 100644 --- a/src/alu.c +++ b/src/alu.c @@ -350,7 +350,7 @@ static void parse_quoted_character(char closing_quote) } // parse character - value = (intval_t) Encoding_encode_char(GotByte); + value = (intval_t) encoding_encode_char(GotByte); // Read closing quote (hopefully) if (GetQuotedByte() == closing_quote) GetByte(); // if length == 1, proceed with next byte diff --git a/src/encoding.c b/src/encoding.c index b004a79..4a8741a 100644 --- a/src/encoding.c +++ b/src/encoding.c @@ -16,43 +16,101 @@ #include "tree.h" -// Encoder function type definition -typedef char (*encoder_t)(char) ; +// struct definition +struct encoder { + char (*fn)(char); + // maybe add table pointer? +}; -// Constants +// constants static const char s_pet[] = "pet"; static const char s_raw[] = "raw"; static const char s_scr[] = "scr"; -// Variables -static char outermost_table[256]; // space for encoding table... -static char *loaded_table = outermost_table; // ...loaded from file -// predefined stuff -static struct ronode *encoder_tree = NULL; // tree to hold encoders +// variables +static char outermost_table[256]; // space for encoding table... +static char *loaded_table = outermost_table; // ...loaded from file +static struct encoder *current_encoder; // gets set before each pass -// Functions +// encoder functions: -// convert character using current encoding -// Conversion function pointer. No init needed: gets set before each pass. -char (*Encoding_encode_char)(char); -// Insert string(s) -static enum eos encode_string(encoder_t inner_encoder, char xor) +// convert raw to raw (do not convert at all) +static char encoderfn_raw(char byte) { - encoder_t outer_encoder = Encoding_encode_char; // buffer encoder + return byte; +} +// convert raw to petscii +static char encoderfn_pet(char byte) +{ + if ((byte >= 'A') && (byte <= 'Z')) + return (char) (byte | 0x80); // FIXME - check why SAS-C + if ((byte >= 'a') && (byte <= 'z')) // wants these casts. + return (char) (byte - 32); // There are more below. + return byte; +} +// convert raw to C64 screencode +static char encoderfn_scr(char byte) +{ + if ((byte >= 'a') && (byte <= 'z')) + return (char) (byte - 96); // shift uppercase down + if ((byte >= '[') && (byte <= '_')) + return (char) (byte - 64); // shift [\]^_ down + if (byte == '`') + return 64; // shift ` down + if (byte == '@') + return 0; // shift @ down + return byte; +} +// convert raw to whatever is defined in table +static char encoderfn_file(char byte) +{ + return loaded_table[(unsigned char) byte]; +} + + +// predefined encoder structs: + + +static struct encoder encoder_raw = { + encoderfn_raw +}; +static struct encoder encoder_pet = { + encoderfn_pet +}; +static struct encoder encoder_scr = { + encoderfn_scr +}; +static struct encoder encoder_file = { + encoderfn_file +}; + + +// functions + +// convert character using current encoding (exported for use by alu.c) +char encoding_encode_char(char byte) +{ + return current_encoder->fn(byte); +} + +// insert string(s) +static enum eos encode_string(struct encoder *inner_encoder, char xor) +{ + struct encoder *outer_encoder = current_encoder; // buffer encoder // make given encoder the current one (for ALU-parsed values) - Encoding_encode_char = inner_encoder; + current_encoder = inner_encoder; do { if (GotByte == '"') { // read initial character GetQuotedByte(); // send characters until closing quote is reached while (GotByte && (GotByte != '"')) { - output_8(xor ^ Encoding_encode_char(GotByte)); + output_8(xor ^ current_encoder->fn(GotByte)); GetQuotedByte(); } if (GotByte == CHAR_EOS) @@ -67,99 +125,18 @@ static enum eos encode_string(encoder_t inner_encoder, char xor) output_8(ALU_any_int()); } } while (Input_accept_comma()); - Encoding_encode_char = outer_encoder; // reactivate buffered encoder + current_encoder = outer_encoder; // reactivate buffered encoder return ENSURE_EOS; } -// Insert text string (default format) -static enum eos PO_text(void) -{ - return encode_string(Encoding_encode_char, 0); -} - -// convert raw to raw (do not convert at all) -static char encoder_raw(char byte) -{ - return byte; -} - -// Insert raw string -static enum eos PO_raw(void) -{ - return encode_string(encoder_raw, 0); -} - -// convert raw to petscii -static char encoder_pet(char byte) -{ - if ((byte >= 'A') && (byte <= 'Z')) - return (char) (byte | 0x80); // FIXME - check why SAS-C - if ((byte >= 'a') && (byte <= 'z')) // wants these casts. - return (char) (byte - 32); // There are more below. - return byte; -} - -// Insert PetSCII string -static enum eos PO_pet(void) -{ - return encode_string(encoder_pet, 0); -} - -// convert raw to C64 screencode -static char encoder_scr(char byte) -{ - if ((byte >= 'a') && (byte <= 'z')) - return (char) (byte - 96); // shift uppercase down - if ((byte >= '[') && (byte <= '_')) - return (char) (byte - 64); // shift [\]^_ down - if (byte == '`') - return 64; // shift ` down - if (byte == '@') - return 0; // shift @ down - return byte; -} - -// Insert screencode string -static enum eos PO_scr(void) -{ - return encode_string(encoder_scr, 0); -} - -// Insert screencode string, XOR'd -static enum eos PO_scrxor(void) -{ - intval_t num = ALU_any_int(); - - if (Input_accept_comma()) - return encode_string(encoder_scr, num); - Throw_error(exception_syntax); - return SKIP_REMAINDER; -} - -// "!cbm" pseudo opcode (now obsolete) -static enum eos PO_cbm(void) -{ - Throw_error("\"!cbm\" is obsolete; use \"!ct pet\" instead."); - return ENSURE_EOS; -} - -// -static char encoder_file(char byte) -{ - return loaded_table[(unsigned char) byte]; -} - // read encoding table from file static enum eos user_defined_encoding(void) { FILE *fd; char local_table[256], *buffered_table = loaded_table; - encoder_t buffered_encoder = Encoding_encode_char; + struct encoder *buffered_encoder = current_encoder; - // if file name is missing, don't bother continuing - if (Input_read_filename(TRUE)) - return SKIP_REMAINDER; fd = fopen(GLOBALDYNABUF_CURRENT, FILE_READBINARY); if (fd) { if (fread(local_table, sizeof(char), 256, fd) != 256) @@ -168,88 +145,146 @@ static enum eos user_defined_encoding(void) } else { Throw_error(exception_cannot_open_input_file); } - Encoding_encode_char = encoder_file; // activate new encoding + current_encoder = &encoder_file; // activate new encoding loaded_table = local_table; // activate local table // If there's a block, parse that and then restore old values - if (Parse_optional_block()) - Encoding_encode_char = buffered_encoder; - else + if (Parse_optional_block()) { + current_encoder = buffered_encoder; + } else { // if there's *no* block, the table must be used from now on. // copy the local table to the "outer" table memcpy(buffered_table, local_table, 256); + } // re-activate "outer" table (it might have been changed by memcpy()) loaded_table = buffered_table; return ENSURE_EOS; } +// keywords for "!convtab" pseudo opcode +static struct ronode *encoder_tree = NULL; // tree to hold encoders +static struct ronode encoder_list[] = { +//no! PREDEFNODE("file", &encoder_file), "!ct file" is not needed; just use {} after initial loading of table! + PREDEFNODE(s_pet, &encoder_pet), + PREDEFNODE(s_raw, &encoder_raw), + PREDEFLAST(s_scr, &encoder_scr), + // ^^^^ this marks the last element +}; + + // use one of the pre-defined encodings (raw, pet, scr) static enum eos predefined_encoding(void) { void *node_body; char local_table[256], *buffered_table = loaded_table; - encoder_t buffered_encoder = Encoding_encode_char; + struct encoder *buffered_encoder = current_encoder; // use one of the pre-defined encodings if (Input_read_and_lower_keyword()) { - // search for tree item - if (Tree_easy_scan(encoder_tree, &node_body, GlobalDynaBuf)) - Encoding_encode_char = (encoder_t) node_body; // activate new encoder - else + // make sure tree is initialised + if (encoder_tree == NULL) + Tree_add_table(&encoder_tree, encoder_list); + // perform lookup + if (Tree_easy_scan(encoder_tree, &node_body, GlobalDynaBuf)) { + current_encoder = (struct encoder *) node_body; // activate new encoder + } else { Throw_error("Unknown encoding."); + } } loaded_table = local_table; // activate local table // If there's a block, parse that and then restore old values if (Parse_optional_block()) - Encoding_encode_char = buffered_encoder; + current_encoder = buffered_encoder; // re-activate "outer" table loaded_table = buffered_table; return ENSURE_EOS; } -// Set current encoding ("!convtab" pseudo opcode) -static enum eos PO_convtab(void) + +// exported functions + +// set "raw" as default encoding +void encoding_passinit(void) { - if ((GotByte == '<') || (GotByte == '"')) + current_encoder = &encoder_raw; +} + + + +// FIXME - move this to pseudoopcodes.c: + +// insert text string (default format) +static enum eos po_text(void) +{ + return encode_string(current_encoder, 0); +} + +// insert raw string +static enum eos po_raw(void) +{ + return encode_string(&encoder_raw, 0); +} + +// insert PetSCII string +static enum eos po_pet(void) +{ + return encode_string(&encoder_pet, 0); +} + +// insert screencode string +static enum eos po_scr(void) +{ + return encode_string(&encoder_scr, 0); +} + +// insert screencode string, XOR'd +static enum eos po_scrxor(void) +{ + intval_t num = ALU_any_int(); + + if (Input_accept_comma() == FALSE) { + Throw_error(exception_syntax); + return SKIP_REMAINDER; + } + return encode_string(&encoder_scr, num); +} + +// "!cbm" pseudo opcode (now obsolete) +static enum eos po_cbm(void) +{ + Throw_error("\"!cbm\" is obsolete; use \"!ct pet\" instead."); + return ENSURE_EOS; +} + +// Set current encoding ("!convtab" pseudo opcode) +static enum eos po_convtab(void) +{ + if ((GotByte == '<') || (GotByte == '"')) { + // if file name is missing, don't bother continuing + if (Input_read_filename(TRUE)) + return SKIP_REMAINDER; return user_defined_encoding(); - else + } else { return predefined_encoding(); + } } // pseudo opcode table static struct ronode pseudo_opcodes[] = { - PREDEFNODE(s_cbm, PO_cbm), - PREDEFNODE("ct", PO_convtab), - PREDEFNODE("convtab", PO_convtab), - PREDEFNODE(s_pet, PO_pet), - PREDEFNODE(s_raw, PO_raw), - PREDEFNODE(s_scr, PO_scr), - PREDEFNODE(s_scrxor, PO_scrxor), - PREDEFNODE("text", PO_text), - PREDEFLAST("tx", PO_text), + PREDEFNODE(s_cbm, po_cbm), + PREDEFNODE("ct", po_convtab), + PREDEFNODE("convtab", po_convtab), + PREDEFNODE(s_pet, po_pet), + PREDEFNODE(s_raw, po_raw), + PREDEFNODE(s_scr, po_scr), + PREDEFNODE(s_scrxor, po_scrxor), + PREDEFNODE("text", po_text), + PREDEFLAST("tx", po_text), // ^^^^ this marks the last element }; -// keywords for "!convtab" pseudo opcode -static struct ronode encoders[] = { - PREDEFNODE(s_pet, encoder_pet), - PREDEFNODE(s_raw, encoder_raw), - PREDEFLAST(s_scr, encoder_scr), - // ^^^^ this marks the last element -}; - - -// Exported functions - -// register pseudo opcodes and build keyword tree for encoders +// register pseudo opcodes void Encoding_init(void) { - Tree_add_table(&encoder_tree, encoders); Tree_add_table(&pseudo_opcode_tree, pseudo_opcodes); } - -// Set "raw" as default encoding -void Encoding_passinit(void) -{ - Encoding_encode_char = encoder_raw; -} diff --git a/src/encoding.h b/src/encoding.h index edead14..60ff776 100644 --- a/src/encoding.h +++ b/src/encoding.h @@ -1,5 +1,5 @@ // ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2009 Marco Baye +// Copyright (C) 1998-2014 Marco Baye // Have a look at "acme.c" for further info // // Character encoding stuff @@ -7,14 +7,14 @@ #define encoding_H -// Prototypes +// prototypes -// register pseudo opcodes and build keyword tree for encoders +// register pseudo opcodes (FIXME - remove!) extern void Encoding_init(void); // convert character using current encoding -extern char (*Encoding_encode_char)(char); -// Set "raw" as default encoding -extern void Encoding_passinit(void); +extern char encoding_encode_char(char); +// set "raw" as default encoding +extern void encoding_passinit(void); #endif diff --git a/src/output.c b/src/output.c index 3ca503f..d21a2bc 100644 --- a/src/output.c +++ b/src/output.c @@ -59,8 +59,6 @@ static struct output *out = &default_output; struct vcpu CPU_state; // current CPU state // FIXME - move file format stuff to some other .c file! -// predefined stuff -static struct ronode *file_format_tree = NULL; // tree to hold output formats // possible file formats enum output_format { OUTPUT_FORMAT_UNSPECIFIED, // default (uses "plain" actually) @@ -68,7 +66,9 @@ enum output_format { OUTPUT_FORMAT_CBM, // load address, code (default for "!to" pseudo opcode) OUTPUT_FORMAT_PLAIN // code only }; -static struct ronode file_formats[] = { +// predefined stuff +static struct ronode *file_format_tree = NULL; // tree to hold output formats +static struct ronode file_format_list[] = { PREDEFNODE("apple", OUTPUT_FORMAT_APPLE), PREDEFNODE(s_cbm, OUTPUT_FORMAT_CBM), // PREDEFNODE("o65", OUTPUT_FORMAT_O65), @@ -269,7 +269,7 @@ int output_set_output_format(void) // make sure tree is initialised if (file_format_tree == NULL) - Tree_add_table(&file_format_tree, file_formats); + Tree_add_table(&file_format_tree, file_format_list); // perform lookup if (!Tree_easy_scan(file_format_tree, &node_body, GlobalDynaBuf)) return 1;