From 9628f69f4ea6c87d3e50a1c9e3370144d8c820dc Mon Sep 17 00:00:00 2001 From: marcobaye Date: Fri, 22 Dec 2017 22:55:36 +0000 Subject: [PATCH] ACME release 0.96.4: Fixed bug in zero page wrap-around warnings. Added "!xor" pseudo op. Added "-I" CLI switch. git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@97 4df02467-bbd4-4a76-a152-e7ce94205b78 --- docs/AllPOs.txt | 18 +++++++++ docs/Changes.txt | 14 +++++++ docs/Errors.txt | 2 - docs/Help.txt | 4 +- docs/QuickRef.txt | 6 +++ src/_amiga.h | 3 ++ src/_dos.h | 3 ++ src/_riscos.h | 3 ++ src/_std.h | 3 ++ src/acme.c | 21 ++++++++--- src/encoding.c | 13 ++----- src/encoding.h | 5 ++- src/input.c | 89 +++++++++++++++++++++++++++++++++++++++++++-- src/input.h | 23 ++++++++++-- src/mnemo.c | 13 +++---- src/output.c | 14 ++++++- src/output.h | 2 + src/pseudoopcodes.c | 72 +++++++++++++++++++++++++----------- src/version.h | 4 +- 19 files changed, 251 insertions(+), 61 deletions(-) diff --git a/docs/AllPOs.txt b/docs/AllPOs.txt index 0cc0e69..31da14b 100644 --- a/docs/AllPOs.txt +++ b/docs/AllPOs.txt @@ -798,6 +798,24 @@ Examples: !to "TinyDemo", cbm ; define output file + format ; Useful if you want to store your code in an EPROM. +Call: !xor EXPRESSION [ { BLOCK } ] +Purpose: Change the value to XOR all output bytes with (the + value defaults to zero on startup). This "encryption" + facility was added to compensate for the shortcomings + of the "!scrxor" pseudo opcode, which only XORs + strings and characters, but not numbers. + When used with block syntax, the previously chosen + value is restored afterwards. +Parameters: EXPRESSION: Any formula the value parser accepts. + BLOCK: A block of assembler statements. +Examples: ; first as normal screencodes: + !scr "Hello everybody...", GROUPLOGOCHAR + ; and now as inverted screencodes: + !xor $80 { + !scr "Hello everybody...", GROUPLOGOCHAR + } + + ---------------------------------------------------------------------- Section: Offset assembly ---------------------------------------------------------------------- diff --git a/docs/Changes.txt b/docs/Changes.txt index 404abcb..ec6fafd 100644 --- a/docs/Changes.txt +++ b/docs/Changes.txt @@ -12,6 +12,20 @@ platform used. There should be another help file in this archive outlining the platform specific changes. +---------------------------------------------------------------------- +Section: New in release 0.96.4 +---------------------------------------------------------------------- + +Bugfix: Removed warnings about zero page wrap-around for the 65816's + 24-bit pointers (because wrap-around does not actually happen). + Thanks to Johann Klasek for reporting this. +Added "!xor" pseudo opcode to compensate for the shortcomings of the + "!scrxor" pseudo opcode. Thanks to spider-j for the initial bug + report. +Added "-I" CLI switch to add search paths for input files. Thanks to + peiselulli for the suggestion. + + ---------------------------------------------------------------------- Section: New in release 0.96.3 ---------------------------------------------------------------------- diff --git a/docs/Errors.txt b/docs/Errors.txt index 6a21549..3f7a52f 100644 --- a/docs/Errors.txt +++ b/docs/Errors.txt @@ -161,8 +161,6 @@ Zeropage pointer wraps around from $ff to $00 A zeropage-indirect addressing mode uses $ff as the argument. The 6502 will then fetch the second pointer byte from $00 instead of $0100, therefore this warning is issued. - With the 65816's three-byte pointers, this warning is also given - for $fe arguments. ...called from here. If warnings and/or errors are output during a macro call, messages diff --git a/docs/Help.txt b/docs/Help.txt index 85a21b2..8c76b3b 100644 --- a/docs/Help.txt +++ b/docs/Help.txt @@ -6,7 +6,7 @@ - free software - - (C) 1998-2016 Marco Baye + (C) 1998-2017 Marco Baye ---------------------------------------------------------------------- @@ -14,7 +14,7 @@ Section: Copyright ---------------------------------------------------------------------- ACME - a crossassembler for producing 6502/6510/65c02/65816 code. -Copyright (C) 1998-2016 Marco Baye +Copyright (C) 1998-2017 Marco Baye The ACME icon was designed by Wanja "Brix" Gayk This program is free software; you can redistribute it and/or modify diff --git a/docs/QuickRef.txt b/docs/QuickRef.txt index 74f3475..e43455e 100644 --- a/docs/QuickRef.txt +++ b/docs/QuickRef.txt @@ -251,6 +251,12 @@ Available options are: "-DSYSTEM=128" could build the C128 version of the software (using conditional assembly in your source code file). + -I PATH/TO/DIR add search path for input files + This option allows to add a directory to the search list for + input files. If an input file cannot be found in the current + working directory, all directories in the search list are + tried (the first match is used). + -W fine-tune amount and type of warnings -Wno-label-indent Disables warnings about labels not being in the leftmost diff --git a/src/_amiga.h b/src/_amiga.h index 315b601..474c4ef 100644 --- a/src/_amiga.h +++ b/src/_amiga.h @@ -15,6 +15,9 @@ // convert UNIX-style pathname to Amiga-style pathname (no change) #define PLATFORM_CONVERTPATHCHAR(a) (a) +// directory separator for include paths +#define DIRECTORY_SEPARATOR '\0' // actually '/', but paths ending on ':' are ok, so auto-adding '/' is bad) + // string containing the prefix for accessing files from the library tree #define PLATFORM_LIBPREFIX "progdir:acme_lib/" #define NO_NEED_FOR_ENV_VAR diff --git a/src/_dos.h b/src/_dos.h index 4e3c288..ab9515e 100644 --- a/src/_dos.h +++ b/src/_dos.h @@ -18,6 +18,9 @@ // convert UNIX-style pathname to DOS-style pathname #define PLATFORM_CONVERTPATHCHAR(a) DOS_convert_path_char(a) +// directory separator for include paths +#define DIRECTORY_SEPARATOR '\\' + // string containing the prefix for accessing files from the library tree #define PLATFORM_LIBPREFIX DOS_lib_prefix diff --git a/src/_riscos.h b/src/_riscos.h index bea08a6..945dcba 100644 --- a/src/_riscos.h +++ b/src/_riscos.h @@ -17,6 +17,9 @@ // convert UNIX-style pathname to RISC OS-style pathname #define PLATFORM_CONVERTPATHCHAR(a) RISCOS_convert_path_char(a) +// directory separator for include paths +#define DIRECTORY_SEPARATOR '\0' // actually '.', but paths ending on ':' are ok, so auto-adding '.' is bad) + // string containing the prefix for accessing files from the library tree #define PLATFORM_LIBPREFIX "ACME_Lib:" #define NO_NEED_FOR_ENV_VAR diff --git a/src/_std.h b/src/_std.h index ecddf64..826d811 100644 --- a/src/_std.h +++ b/src/_std.h @@ -15,6 +15,9 @@ // convert UNIX-style pathname to AnyOS-style pathname (no change) #define PLATFORM_CONVERTPATHCHAR(a) (a) +// directory separator for include paths +#define DIRECTORY_SEPARATOR '/' + // string containing the prefix for accessing files from the library tree #define PLATFORM_LIBPREFIX AnyOS_lib_prefix diff --git a/src/acme.c b/src/acme.c index 9bb3fb1..bd874dd 100644 --- a/src/acme.c +++ b/src/acme.c @@ -131,6 +131,7 @@ static void show_help_and_exit(void) " --" OPTION_MAXDEPTH " NUMBER set recursion depth for macro calls and !src\n" " -vDIGIT set verbosity level\n" " -DSYMBOL=VALUE define global symbol\n" +" -I PATH/TO/DIR add search path for input files\n" // as long as there is only one -W option: #define OPTIONWNO_LABEL_INDENT "no-label-indent" " -W" OPTIONWNO_LABEL_INDENT " suppress warnings about indented labels\n" @@ -185,7 +186,7 @@ int ACME_finalize(int exit_code) report_close(report); if (symbollist_filename) { - fd = fopen(symbollist_filename, FILE_WRITETEXT); + fd = fopen(symbollist_filename, FILE_WRITETEXT); // FIXME - what if filename is given via !sl in sub-dir? fix path! if (fd) { symbols_list(fd); fclose(fd); @@ -220,7 +221,7 @@ static void save_output_file(void) fputs("No output file specified (use the \"-o\" option or the \"!to\" pseudo opcode).\n", stderr); return; } - fd = fopen(output_filename, FILE_WRITEBINARY); + fd = fopen(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); @@ -488,17 +489,24 @@ static char short_option(const char *argument) case 'D': // "-D" define constants define_symbol(argument + 1); goto done; - case 'h': // "-h" shows help - show_help_and_exit(); case 'f': // "-f" selects output format set_output_format(); break; - case 'o': // "-o" selects output filename - output_filename = cliargs_safe_get_next(name_outfile); + case 'h': // "-h" shows help + show_help_and_exit(); break; + case 'I': // "-I" adds an include directory + if (argument[1]) + includepaths_add(argument + 1); + else + 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); break; + case 'o': // "-o" selects output filename + output_filename = cliargs_safe_get_next(name_outfile); + break; case 'r': // "-r" selects report filename report_filename = cliargs_safe_get_next(arg_reportfile); break; @@ -553,6 +561,7 @@ int main(int argc, const char *argv[]) PLATFORM_INIT; // prepare a buffer large enough to hold pointers to "-D" switch values // cli_defines = safe_malloc(argc * sizeof(*cli_defines)); + includepaths_init(); // must be done before cli arg handling // handle command line arguments cliargs_handle_options(short_option, long_option); // generate list of files to process diff --git a/src/encoding.c b/src/encoding.c index 45d16b7..658272d 100644 --- a/src/encoding.c +++ b/src/encoding.c @@ -109,17 +109,10 @@ void encoding_passinit(void) } // try to load encoding table from given file -void encoding_load(char target[256], const char *filename) +void encoding_load_from_file(char target[256], FILE *stream) { - FILE *fd = fopen(filename, FILE_READBINARY); - - if (fd) { - if (fread(target, sizeof(char), 256, fd) != 256) - Throw_error("Conversion table incomplete."); - fclose(fd); - } else { - Throw_error(exception_cannot_open_input_file); - } + 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) diff --git a/src/encoding.h b/src/encoding.h index 64fd07d..ada5d71 100644 --- a/src/encoding.h +++ b/src/encoding.h @@ -7,6 +7,9 @@ #define encoding_H +#include // 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; @@ -23,7 +26,7 @@ extern char encoding_encode_char(char byte); // set "raw" as default encoding extern void encoding_passinit(void); // try to load encoding table from given file -extern void encoding_load(char target[256], const char *filename); +extern void encoding_load_from_file(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); diff --git a/src/input.c b/src/input.c index 25fa8a6..2538f61 100644 --- a/src/input.c +++ b/src/input.c @@ -472,13 +472,16 @@ int Input_read_and_lower_keyword(void) return length; } -// Try to read a file name. If "allow_library" is TRUE, library access by using -// <...> quoting is possible as well. The file name given in the assembler -// source code is converted from UNIX style to platform style. +// Try to read a file name. +// If "allow_library" is TRUE, library access by using <...> quoting +// is possible as well. If "uses_lib" is non-NULL, info about library +// usage is stored there. +// The file name given in the assembler source code is converted from +// UNIX style to platform style. // Returns whether error occurred (TRUE on error). Filename in GlobalDynaBuf. // Errors are handled and reported, but caller should call // Input_skip_remainder() then. -int Input_read_filename(int allow_library) +int Input_read_filename(int allow_library, int *uses_lib) { char *lib_prefix, end_quote; @@ -487,6 +490,8 @@ int Input_read_filename(int allow_library) SKIPSPACE(); // check for library access if (GotByte == '<') { + if (uses_lib) + *uses_lib = 1; // if library access forbidden, complain if (allow_library == FALSE) { Throw_error("Writing to library not supported."); @@ -506,6 +511,8 @@ int Input_read_filename(int allow_library) DynaBuf_add_string(GlobalDynaBuf, lib_prefix); end_quote = '>'; } else { + if (uses_lib) + *uses_lib = 0; if (GotByte == '"') { end_quote = '"'; } else { @@ -569,3 +576,77 @@ int Input_get_force_bit(void) SKIPSPACE(); return force_bit; } + + +// include path stuff - should be moved to its own file: + +// ring list struct +struct ipi { + struct ipi *next, + *prev; + const char *path; +}; +static struct ipi ipi_head; // head element +static struct dynabuf *pathbuf; // buffer to combine search path and file spec + +// init list +void includepaths_init(void) +{ + // init ring list + ipi_head.next = &ipi_head; + ipi_head.prev = &ipi_head; + // init dynabuf + pathbuf = DynaBuf_create(256); +} +// add entry +void includepaths_add(const char *path) +{ + struct ipi *ipi; + + ipi = safe_malloc(sizeof(*ipi)); + ipi->path = path; + ipi->next = &ipi_head; + ipi->prev = ipi_head.prev; + ipi->next->prev = ipi; + ipi->prev->next = ipi; +} +// open file for reading (trying list entries as prefixes) +// "uses_lib" tells whether to access library or to make use of include paths +// file name is expected in GlobalDynaBuf +FILE *includepaths_open_ro(int uses_lib) +{ + FILE *stream; + struct ipi *ipi; + + // first try directly, regardless of whether lib or not: + stream = fopen(GLOBALDYNABUF_CURRENT, FILE_READBINARY); + // if failed and not lib, try include paths: + if ((stream == NULL) && !uses_lib) { + for (ipi = ipi_head.next; ipi != &ipi_head; ipi = ipi->next) { + DYNABUF_CLEAR(pathbuf); + // add first part + DynaBuf_add_string(pathbuf, ipi->path); + // if wanted and possible, ensure last char is directory separator + if (DIRECTORY_SEPARATOR + && pathbuf->size + && (pathbuf->buffer[pathbuf->size - 1] != DIRECTORY_SEPARATOR)) + DynaBuf_append(pathbuf, DIRECTORY_SEPARATOR); + // add second part + DynaBuf_add_string(pathbuf, GLOBALDYNABUF_CURRENT); + // terminate + DynaBuf_append(pathbuf, '\0'); + // try + stream = fopen(pathbuf->buffer, FILE_READBINARY); + //printf("trying <<%s>> - ", pathbuf->buffer); + if (stream) { + //printf("ok\n"); + break; + } else { + //printf("failed\n"); + } + } + } + if (stream == NULL) + Throw_error(exception_cannot_open_input_file); + return stream; +} diff --git a/src/input.h b/src/input.h index 8c49b35..8b69e05 100644 --- a/src/input.h +++ b/src/input.h @@ -99,13 +99,16 @@ extern int Input_read_keyword(void); // Return its length (without terminator). // Zero lengths will produce a "missing string" error. extern int Input_read_and_lower_keyword(void); -// Try to read a file name. If "allow_library" is TRUE, library access by using -// <...> quoting is possible as well. The file name given in the assembler -// source code is converted from UNIX style to platform style. +// Try to read a file name. +// If "allow_library" is TRUE, library access by using <...> quoting +// is possible as well. If "uses_lib" is non-NULL, info about library +// usage is stored there. +// The file name given in the assembler source code is converted from +// UNIX style to platform style. // Returns whether error occurred (TRUE on error). Filename in GlobalDynaBuf. // Errors are handled and reported, but caller should call // Input_skip_remainder() then. -extern int Input_read_filename(int library_allowed); +extern int Input_read_filename(int library_allowed, int *uses_lib); // Try to read a comma, skipping spaces before and after. Return TRUE if comma // found, otherwise FALSE. extern int Input_accept_comma(void); @@ -113,4 +116,16 @@ extern int Input_accept_comma(void); extern int Input_get_force_bit(void); +// include path stuff - should be moved to its own file: + +// init list +extern void includepaths_init(void); +// add entry +extern void includepaths_add(const char *path); +// open file for reading (trying list entries as prefixes) +// "uses_lib" tells whether to access library or to make use of include paths +// file name is expected in GlobalDynaBuf +extern FILE *includepaths_open_ro(int uses_lib); + + #endif diff --git a/src/mnemo.c b/src/mnemo.c index 14e1b73..f04eebb 100644 --- a/src/mnemo.c +++ b/src/mnemo.c @@ -828,10 +828,9 @@ static unsigned int imm_ops(int *force_bit, unsigned char opcode, int immediate_ } // helper function to warn if zp pointer wraps around -// call with bits=0 for 2-byte pointers and bits=1 for 3-byte pointers -static void check_zp_wraparound(struct result *result, int bits) +static void check_zp_wraparound(struct result *result) { - if (((result->val.intval | bits) == 0xff) + if ((result->val.intval == 0xff) && (result->flags & MVALUE_DEFINED)) Throw_warning("Zeropage pointer wraps around from $ff to $00"); } @@ -868,23 +867,21 @@ static void group_main(int index, int immediate_mode) break; case INDIRECT_ADDRESSING: // ($ff) make_command(force_bit, &result, accu_ind8[index]); - check_zp_wraparound(&result, 0); + check_zp_wraparound(&result); break; case INDIRECT_Y_INDEXED_ADDRESSING: // ($ff),y make_command(force_bit, &result, accu_indy8[index]); - check_zp_wraparound(&result, 0); + check_zp_wraparound(&result); break; case INDIRECT_Z_INDEXED_ADDRESSING: // ($ff),z make_command(force_bit, &result, accu_indz8[index]); - check_zp_wraparound(&result, 0); + check_zp_wraparound(&result); break; case LONG_INDIRECT_ADDRESSING: // [$ff] make_command(force_bit, &result, accu_lind8[index]); - check_zp_wraparound(&result, 1); break; case LONG_INDIRECT_Y_INDEXED_ADDRESSING: // [$ff],y make_command(force_bit, &result, accu_lindy8[index]); - check_zp_wraparound(&result, 1); break; case STACK_INDEXED_INDIRECT_Y_INDEXED_ADDRESSING: // ($ff,s),y make_command(force_bit, &result, accu_sindy8[index]); diff --git a/src/output.c b/src/output.c index 138b3e9..ce4ae96 100644 --- a/src/output.c +++ b/src/output.c @@ -49,6 +49,7 @@ struct output { int flags; // segment flags ("overlay" and "invisible", see header file) struct segment list_head; // head element of doubly-linked ring list } segment; + char xor; // output modifier }; @@ -142,7 +143,7 @@ static void real_output(intval_t byte) // write byte and advance ptrs if (report->fd) report_binary(byte & 0xff); // file for reporting, taking also CPU_2add - out->buffer[out->write_idx++] = byte & 0xff; + out->buffer[out->write_idx++] = (byte & 0xff) ^ out->xor; ++CPU_state.add_to_pc; } @@ -478,6 +479,7 @@ void Output_passinit(void) out->segment.start = NO_SEGMENT_START; // TODO - "no active segment" could be made a segment flag! out->segment.max = OUTBUFFERSIZE - 1; out->segment.flags = 0; + out->xor = 0; //vcpu stuff: CPU_state.pc.flags = 0; // not defined yet @@ -541,6 +543,16 @@ void Output_start_segment(intval_t address_change, int segment_flags) } +char output_get_xor(void) +{ + return out->xor; +} +void output_set_xor(char xor) +{ + out->xor = xor; +} + + // set program counter to defined value (FIXME - allow for undefined!) // if start address was given on command line, main loop will call this before each pass. // in addition to that, it will be called on each "* = VALUE". diff --git a/src/output.h b/src/output.h index bd8434d..00168a7 100644 --- a/src/output.h +++ b/src/output.h @@ -87,6 +87,8 @@ extern void Output_save_file(FILE *fd); extern void Output_start_segment(intval_t address_change, int segment_flags); // Show start and end of current segment extern void Output_end_segment(void); +extern char output_get_xor(void); +extern void output_set_xor(char xor); // set program counter to defined value (TODO - allow undefined!) extern void vcpu_set_pc(intval_t new_pc, int flags); diff --git a/src/pseudoopcodes.c b/src/pseudoopcodes.c index bb7d6dc..1540799 100644 --- a/src/pseudoopcodes.c +++ b/src/pseudoopcodes.c @@ -89,6 +89,26 @@ static enum eos po_initmem(void) } +// change output "encryption" ("!xor" pseudo opcode) +static enum eos po_xor(void) +{ + char old_value; + intval_t change; + + old_value = output_get_xor(); + change = ALU_any_int(); + if ((change > 0xff) || (change < -0x80)) { + Throw_error(exception_number_out_of_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 and format ("!to" pseudo opcode) static enum eos po_to(void) { @@ -99,7 +119,7 @@ static enum eos po_to(void) // read filename to global dynamic buffer // if no file name given, exit (complaining will have been done) - if (Input_read_filename(FALSE)) + if (Input_read_filename(FALSE, NULL)) return SKIP_REMAINDER; // only act upon this pseudo opcode in first pass @@ -260,13 +280,16 @@ static enum eos obsolete_po_cbm(void) } // read encoding table from file -static enum eos user_defined_encoding(void) +static enum eos user_defined_encoding(FILE *stream) { char local_table[256], *buffered_table = encoding_loaded_table; const struct encoder *buffered_encoder = encoder_current; - encoding_load(local_table, GLOBALDYNABUF_CURRENT); + if (stream) { + encoding_load_from_file(local_table, stream); + fclose(stream); + } encoder_current = &encoder_file; // activate new encoding encoding_loaded_table = local_table; // activate local table // If there's a block, parse that and then restore old values @@ -306,11 +329,16 @@ static enum eos predefined_encoding(void) // set current encoding ("!convtab" pseudo opcode) static enum eos po_convtab(void) { + int uses_lib; + FILE *stream; + if ((GotByte == '<') || (GotByte == '"')) { // if file name is missing, don't bother continuing - if (Input_read_filename(TRUE)) + if (Input_read_filename(TRUE, &uses_lib)) return SKIP_REMAINDER; - return user_defined_encoding(); + + stream = includepaths_open_ro(uses_lib); + return user_defined_encoding(stream); } else { return predefined_encoding(); } @@ -382,20 +410,21 @@ static enum eos po_scrxor(void) // FIXME - split this into "parser" and "worker" fn and move worker fn somewhere else. static enum eos po_binary(void) { - FILE *fd; + int uses_lib; + FILE *stream; int byte; intval_t size = -1, // means "not given" => "until EOF" skip = 0; // if file name is missing, don't bother continuing - if (Input_read_filename(TRUE)) + if (Input_read_filename(TRUE, &uses_lib)) return SKIP_REMAINDER; + // try to open file - fd = fopen(GLOBALDYNABUF_CURRENT, FILE_READBINARY); - if (fd == NULL) { - Throw_error(exception_cannot_open_input_file); + stream = includepaths_open_ro(uses_lib); + if (stream == NULL) return SKIP_REMAINDER; - } + // read optional arguments if (Input_accept_comma()) { if (ALU_optional_defined_int(&size) @@ -411,11 +440,11 @@ static enum eos po_binary(void) output_skip(size); // really including is useless anyway } else { // really insert file - fseek(fd, skip, SEEK_SET); // set read pointer + fseek(stream, skip, SEEK_SET); // set read pointer // if "size" non-negative, read "size" bytes. // otherwise, read until EOF. while (size != 0) { - byte = getc(fd); + byte = getc(stream); if (byte == EOF) break; Output_byte(byte); @@ -429,7 +458,7 @@ static enum eos po_binary(void) while (--size); } } - fclose(fd); + fclose(stream); // if verbose, produce some output if ((pass_count == 0) && (config.process_verbosity > 1)) { int amount = vcpu_get_statement_size(); @@ -663,7 +692,7 @@ static enum eos po_symbollist(void) // read filename to global dynamic buffer // if no file name given, exit (complaining will have been done) - if (Input_read_filename(FALSE)) + if (Input_read_filename(FALSE, NULL)) return SKIP_REMAINDER; // only process this pseudo opcode in first pass @@ -730,7 +759,8 @@ static enum eos obsolete_po_subzone(void) // include source file ("!source" or "!src"). has to be re-entrant. static enum eos po_source(void) // now GotByte = illegal char { - FILE *fd; + int uses_lib; + FILE *stream; char local_gotbyte; struct input new_input, *outer_input; @@ -740,11 +770,12 @@ static enum eos po_source(void) // now GotByte = illegal char if (--source_recursions_left < 0) Throw_serious_error("Too deeply nested. Recursive \"!source\"?"); // read file name. quit function on error - if (Input_read_filename(TRUE)) + if (Input_read_filename(TRUE, &uses_lib)) return SKIP_REMAINDER; // if file could be opened, parse it. otherwise, complain - if ((fd = fopen(GLOBALDYNABUF_CURRENT, FILE_READBINARY))) { + stream = includepaths_open_ro(uses_lib); + if (stream) { #ifdef __GNUC__ char filename[GlobalDynaBuf->size]; // GCC can do this #else @@ -755,14 +786,12 @@ static enum eos po_source(void) // now GotByte = illegal char outer_input = Input_now; // remember old input local_gotbyte = GotByte; // CAUTION - ugly kluge Input_now = &new_input; // activate new input - flow_parse_and_close_file(fd, filename); + flow_parse_and_close_file(stream, filename); Input_now = outer_input; // restore previous input GotByte = local_gotbyte; // CAUTION - ugly kluge #ifndef __GNUC__ free(filename); // GCC auto-frees #endif - } else { - Throw_error(exception_cannot_open_input_file); } // leave nesting level ++source_recursions_left; @@ -1064,6 +1093,7 @@ static enum eos po_endoffile(void) // pseudo opcode table static struct ronode pseudo_opcode_list[] = { PREDEFNODE("initmem", po_initmem), + PREDEFNODE("xor", po_xor), PREDEFNODE("to", po_to), PREDEFNODE(s_8, po_byte), PREDEFNODE(s_08, po_byte), diff --git a/src/version.h b/src/version.h index 4455673..24eac16 100644 --- a/src/version.h +++ b/src/version.h @@ -7,9 +7,9 @@ #define version_H -#define RELEASE "0.96.3" // update before release FIXME +#define RELEASE "0.96.4" // update before release FIXME #define CODENAME "Fenchurch" // update before release -#define CHANGE_DATE "3 Nov" // update before release FIXME +#define CHANGE_DATE "22 Dec" // update before release FIXME #define CHANGE_YEAR "2017" // update before release //#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/" #define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME