mirror of
https://github.com/uffejakobsen/acme.git
synced 2025-04-13 08:37:03 +00:00
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
This commit is contained in:
parent
f23a38de8c
commit
9628f69f4e
@ -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
|
||||
----------------------------------------------------------------------
|
||||
|
@ -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
|
||||
----------------------------------------------------------------------
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
21
src/acme.c
21
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
|
||||
|
@ -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)
|
||||
|
@ -7,6 +7,9 @@
|
||||
#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;
|
||||
@ -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);
|
||||
|
||||
|
89
src/input.c
89
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;
|
||||
}
|
||||
|
23
src/input.h
23
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
|
||||
|
13
src/mnemo.c
13
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]);
|
||||
|
14
src/output.c
14
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".
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user