diff --git a/docs/Upgrade.txt b/docs/Upgrade.txt index f406ec8..507498a 100644 --- a/docs/Upgrade.txt +++ b/docs/Upgrade.txt @@ -65,7 +65,7 @@ of the lower eight bits is the same. But if you have written any code where the numerical value of a PetSCII character is used for computations _in_the_source_code_, please check those computations. -Use the "--dialect 0.94.12" CLI switch to get the old behavior +Use the "--dialect 0.95.2" CLI switch to get the old behavior concerning a) double quotes and b) backslashes. There is no way to get the old behavior concerning c) character values, because, as explained above, the old behavior was architecture-dependent, which is a bad @@ -81,7 +81,7 @@ In 6510 mode, ACME now outputs 0x0b instead of 0x2b when assembling the undocumented ("illegal") ANC #imm8 instruction. Both opcodes do the same thing, this was only changed because all other mnemonics use the lowest-numbered possible opcode as well. -Forcing the old behavior via the "--dialect" switch is not supported. +Use the "--dialect 0.94.12" CLI switch to get the old behavior. diff --git a/src/_amiga.h b/src/_amiga.h index 05016b0..f996e3f 100644 --- a/src/_amiga.h +++ b/src/_amiga.h @@ -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 // // Platform specific stuff (in this case, for AmigaOS) @@ -15,12 +15,13 @@ // convert UNIX-style pathname to Amiga-style pathname (no change) //#define PLATFORM_CONVERTPATH(p) -// directory separator for include paths -#define DIRECTORY_SEPARATOR '\0' // actually '/', but paths ending on ':' are ok, so auto-adding '/' is bad) +// directory separators for search paths +#define DIRECTORY_SEPARATOR '/' +#define ALTERNATIVE_DIR_SEP ':' // string containing the prefix for accessing files from the library tree -#define PLATFORM_LIBPREFIX "progdir:acme_lib/" -#define NO_NEED_FOR_ENV_VAR +#define PLATFORM_LIBPREFIX "progdir:acme_lib/" +#define PLATFORM_NEEDS_ENV_VAR 0 // no "ACME" environment variable needed // setting file types of created files #define PLATFORM_SETFILETYPE_APPLE(a) diff --git a/src/_dos.c b/src/_dos.c index 330c369..3bc5513 100644 --- a/src/_dos.c +++ b/src/_dos.c @@ -7,33 +7,6 @@ #define platform_C -#include -#include "dynabuf.h" - - -// variables -char *DOS_lib_prefix = NULL; // header string of library tree - - -// used as PLATFORM_INIT: reads "ACME" environment variable -void DOS_entry(void) -{ - char *env_var; - - // Find out the path of ACME's library - env_var = getenv("ACME"); - // if environment variable was found, make a copy - if (env_var) { - dynabuf_clear(GlobalDynaBuf); - // copy environment variable to global dynamic buffer - dynabuf_add_string(GlobalDynaBuf, env_var); - dynabuf_append(GlobalDynaBuf, '\\'); // add dir separator - dynabuf_append(GlobalDynaBuf, '\0'); // add terminator - DOS_lib_prefix = dynabuf_get_copy(GlobalDynaBuf); - } -} - - // convert UNIX-style pathname to DOS-style pathname void DOS_convert_path(char *p) { diff --git a/src/_dos.h b/src/_dos.h index c1bf3b2..6c8be50 100644 --- a/src/_dos.h +++ b/src/_dos.h @@ -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 // // Platform specific stuff (in this case, for DOS, OS/2 and Windows) @@ -13,16 +13,18 @@ // symbolic constants and macros // called once on program startup (could register exit handler, if needed) -#define PLATFORM_INIT DOS_entry() +#define PLATFORM_INIT platform_read_env_var() // convert UNIX-style pathname to DOS-style pathname #define PLATFORM_CONVERTPATH(p) DOS_convert_path(p) -// directory separator for include paths +// directory separators for search paths #define DIRECTORY_SEPARATOR '\\' +#define ALTERNATIVE_DIR_SEP '\\' // dummy // string containing the prefix for accessing files from the library tree -#define PLATFORM_LIBPREFIX DOS_lib_prefix +#define PLATFORM_LIBPREFIX platform_lib_prefix +#define PLATFORM_NEEDS_ENV_VAR 1 // library access needs "ACME" environment variable // setting file types of created files #define PLATFORM_SETFILETYPE_APPLE(a) @@ -51,13 +53,6 @@ do { \ #define PLATFORM_LONGOPTION_CODE -// variables -extern char *DOS_lib_prefix; // header string of library tree - - -// used as PLATFORM_INIT: reads "ACME" environment variable -extern void DOS_entry(void); - // Convert UNIX-style pathname to DOS-style pathname extern void DOS_convert_path(char *p); diff --git a/src/_riscos.h b/src/_riscos.h index d321884..b2bdc3e 100644 --- a/src/_riscos.h +++ b/src/_riscos.h @@ -18,12 +18,13 @@ // convert UNIX-style pathname to RISC OS-style pathname #define PLATFORM_CONVERTPATH(path) RISCOS_convert_path(path) -// directory separator for include paths -#define DIRECTORY_SEPARATOR '\0' // actually '.', but paths ending on ':' are ok, so auto-adding '.' is bad) +// directory separators for search paths +#define DIRECTORY_SEPARATOR '.' +#define ALTERNATIVE_DIR_SEP ':' // string containing the prefix for accessing files from the library tree #define PLATFORM_LIBPREFIX "ACME_Lib:" -#define NO_NEED_FOR_ENV_VAR +#define PLATFORM_NEEDS_ENV_VAR 0 // no "ACME" environment variable needed // setting file types of created files #define PLATFORM_SETFILETYPE_APPLE(a) RISCOS_set_filetype(a, 0xffd) // FIXME - wrong value! diff --git a/src/_std.c b/src/_std.c index 7dc69c3..bbbc809 100644 --- a/src/_std.c +++ b/src/_std.c @@ -7,31 +7,4 @@ #define platform_C -#include -#include "dynabuf.h" - - -// variables -char *AnyOS_lib_prefix = NULL; // header string of library tree - - -// used as PLATFORM_INIT: reads "ACME" environment variable -void AnyOS_entry(void) -{ - char *env_var; - - // Find out the path of ACME's library - env_var = getenv("ACME"); - // if environment variable was found, make a copy - if (env_var) { - dynabuf_clear(GlobalDynaBuf); - // copy environment variable to global dynamic buffer - dynabuf_add_string(GlobalDynaBuf, env_var); - dynabuf_append(GlobalDynaBuf, '/'); // add dir separator - dynabuf_append(GlobalDynaBuf, '\0'); // add terminator - AnyOS_lib_prefix = dynabuf_get_copy(GlobalDynaBuf); - } -} - - #endif diff --git a/src/_std.h b/src/_std.h index 677e860..b13155d 100644 --- a/src/_std.h +++ b/src/_std.h @@ -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 // // Platform specific stuff (in this case, for unknown OSes) @@ -10,16 +10,18 @@ // symbolic constants and macros // called once on program startup (could register exit handler, if needed) -#define PLATFORM_INIT AnyOS_entry() +#define PLATFORM_INIT platform_read_env_var() -// convert UNIX-style pathname to AnyOS-style pathname (no change) +// convert UNIX-style pathname to platform-style pathname (no change) //#define PLATFORM_CONVERTPATH(p) -// directory separator for include paths +// directory separator for search paths #define DIRECTORY_SEPARATOR '/' +#define ALTERNATIVE_DIR_SEP '/' // dummy // string containing the prefix for accessing files from the library tree -#define PLATFORM_LIBPREFIX AnyOS_lib_prefix +#define PLATFORM_LIBPREFIX platform_lib_prefix +#define PLATFORM_NEEDS_ENV_VAR 1 // library access needs "ACME" environment variable // setting the created files' types #define PLATFORM_SETFILETYPE_APPLE(a) @@ -48,12 +50,4 @@ do { \ #define PLATFORM_LONGOPTION_CODE -// variables -extern char *AnyOS_lib_prefix; // header string of library tree - - -// used as PLATFORM_INIT: reads "ACME" environment variable -extern void AnyOS_entry(void); - - #endif diff --git a/src/acme.c b/src/acme.c index 38bebac..4e4d27f 100644 --- a/src/acme.c +++ b/src/acme.c @@ -324,7 +324,7 @@ static void perform_pass(void) // Process toplevel files for (ii = 0; ii < toplevel_src_count; ++ii) { if ((fd = fopen(toplevel_sources_plat[ii], FILE_READBINARY))) { - flow_parse_and_close_platform_file(toplevel_sources_plat[ii], fd); + input_parse_and_close_platform_file(toplevel_sources_plat[ii], fd); } else { fprintf(stderr, "Error: Cannot open toplevel file \"%s\".\n", toplevel_sources_plat[ii]); if (toplevel_sources_plat[ii][0] == '-') @@ -545,6 +545,7 @@ struct dialect_info dialects[] = { {V0_94_12__NEW_FOR_SYNTAX, "0.94.12", "new \"!for\" syntax"}, {V0_95_2__NEW_ANC_OPCODE, "0.95.2", "changed ANC#8 from 0x2b to 0x0b"}, {V0_97__BACKSLASH_ESCAPING, "0.97", "backslash escaping and strings"}, +// {V0_98__PATHS_AND_SYMBOLCHANGE, "0.98", "paths are relative to current file"}, // {V__CURRENT_VERSION, "default", "default"}, {V__FUTURE_VERSION, "future", "enable all experimental features"}, {0, NULL, NULL} // NULLs terminate diff --git a/src/alu.c b/src/alu.c index 841e620..d5800bf 100644 --- a/src/alu.c +++ b/src/alu.c @@ -423,7 +423,7 @@ static void parse_quoted(char closing_quote) // eat closing quote GetByte(); // now convert to unescaped version - if (input_unescape_dynabuf(0)) + if (input_unescape_dynabuf()) goto fail; // escaping error // without backslash escaping, both ' and " are used for single diff --git a/src/flow.c b/src/flow.c index 2c08bae..fd252bd 100644 --- a/src/flow.c +++ b/src/flow.c @@ -264,26 +264,3 @@ void flow_do_while(struct do_while *loop) // then the main loop could choke on unexpected bytes. So we pretend // that we got the outer input's GotByte value magically back. } - - -// parse a whole source code file -// file name must be given in platform style, i.e. -// "directory/basename.extension" on linux, -// "directory.basename/extension" on RISC OS, etc. -// and the pointer must remain valid forever! -void flow_parse_and_close_platform_file(const char *plat_filename, FILE *fd) -{ - // be verbose - if (config.process_verbosity > 2) - printf("Parsing source file '%s'\n", plat_filename); - // set up new input - input_new_platform_file(plat_filename, fd); - // parse block and check end reason - parse_until_eob_or_eof(); - if (GotByte != CHAR_EOF) - Throw_error("Found '}' instead of end-of-file."); - // close sublevel src - // (this looks like we could just use "fd" as arg, but maybe the file - // has been replaced with a different one in the meantime...) - fclose(input_now->src.fd); -} diff --git a/src/flow.h b/src/flow.h index 19bf464..e896088 100644 --- a/src/flow.h +++ b/src/flow.h @@ -73,12 +73,5 @@ extern void flow_store_while_condition(struct condition *condition); // back end function for "!do" pseudo opcode extern void flow_do_while(struct do_while *loop); -// parse a whole source code file -// file name must be given in platform style, i.e. -// "directory/basename.extension" on linux, -// "directory.basename/extension" on RISC OS, etc. -// and the pointer must remain valid forever! -extern void flow_parse_and_close_platform_file(const char *plat_filename, FILE *fd); - #endif diff --git a/src/global.h b/src/global.h index bc1c024..98016fc 100644 --- a/src/global.h +++ b/src/global.h @@ -54,8 +54,8 @@ enum dialect { V0_95_2__NEW_ANC_OPCODE, // v0.95.2 changed ANC#8 from opcode 0x2b to 0x0b V0_97__BACKSLASH_ESCAPING, // v0.97 introduced backslash escaping (and therefore strings) V__CURRENT_VERSION, // "RELEASE" + V0_98__PATHS_AND_SYMBOLCHANGE, // v0.98 fixes paths and allows symbols to change // possible changes in future versions: - // paths should be relative to file, not start dir // ignore leading zeroes? V__FUTURE_VERSION // future (for testing new features) }; diff --git a/src/input.c b/src/input.c index 886dfa7..2df2325 100644 --- a/src/input.c +++ b/src/input.c @@ -26,8 +26,9 @@ const char FILE_READBINARY[] = "rb"; // fake input structure (for error msgs before any real input is established) static struct input outermost = { + "", // file name for resolving paths { - "", // file name + "", // file name where code initially came from (differs during macro execution) 0, // line number }, INPUTSRC_FILE, // fake file access, so no RAM read @@ -44,19 +45,40 @@ struct input *input_now = &outermost; // current input structure // functions -// let current input point to start of file +// parse a whole source code file // file name must be given in platform style, i.e. // "directory/basename.extension" on linux, -// "directory.basename/extension" on RISC OS etc. +// "directory.basename/extension" on RISC OS, etc. // and the pointer must remain valid forever! -// FIXME - there is only one caller, "flow_parse_and_close_platform_file()", so maybe merge? -void input_new_platform_file(const char *plat_filename, FILE *fd) +void input_parse_and_close_platform_file(const char *eternal_plat_filename, FILE *fd) { - input_now->location.plat_filename = plat_filename; - input_now->location.line_number = 1; - input_now->source = INPUTSRC_FILE; - input_now->state = INPUTSTATE_SOF; - input_now->src.fd = fd; + struct input new_input, + *outer_input; + + // be verbose + if (config.process_verbosity > 2) + printf("Parsing source file '%s'\n", eternal_plat_filename); + // set up new input + new_input.plat_pathref_filename = eternal_plat_filename; + new_input.location.plat_filename = eternal_plat_filename; + new_input.location.line_number = 1; + new_input.source = INPUTSRC_FILE; + new_input.state = INPUTSTATE_SOF; + new_input.src.fd = fd; + // remember where outer input struct is + outer_input = input_now; + // activate new input struct + input_now = &new_input; + // parse block and check end reason + parse_until_eob_or_eof(); + if (GotByte != CHAR_EOF) + Throw_error("Found '}' instead of end-of-file."); + // close sublevel src + // (this looks like we could just use "fd" as arg, but maybe the file + // has been replaced with a different one in the meantime...) + fclose(input_now->src.fd); + // restore outer input struct + input_now = outer_input; } @@ -413,16 +435,16 @@ int input_quoted_to_dynabuf(char closing_quote) // process backslash escapes in GlobalDynaBuf (so size might shrink) // returns 1 on errors (escaping errors) // TODO - check: if this is only ever called directly after input_quoted_to_dynabuf, integrate that call here? -int input_unescape_dynabuf(int read_index) +int input_unescape_dynabuf(void) { - int write_index; + int read_index = 0, + write_index = 0; char byte; boolean escaped; if (config.dialect < V0_97__BACKSLASH_ESCAPING) return 0; // ok - write_index = read_index; escaped = FALSE; // CAUTION - contents of dynabuf are not terminated: while (read_index < GlobalDynaBuf->size) { @@ -621,31 +643,30 @@ int input_read_and_lower_keyword(void) // Returns nonzero on error. Filename in GlobalDynaBuf, including terminator. // Errors are handled and reported, but caller should call // input_skip_remainder() then. -static int read_filename_shared_end(int prefix_size) +static int read_filename_shared_end(void) { // check length - if (GlobalDynaBuf->size == prefix_size) { + if (GlobalDynaBuf->size == 0) { Throw_error("No file name given."); return 1; // error } // resolve backslash escapes - if (input_unescape_dynabuf(prefix_size)) + if (input_unescape_dynabuf()) return 1; // escaping error // terminate string dynabuf_append(GlobalDynaBuf, '\0'); #ifdef PLATFORM_CONVERTPATH // platform-specific path name conversion - PLATFORM_CONVERTPATH(GLOBALDYNABUF_CURRENT + prefix_size); + PLATFORM_CONVERTPATH(GLOBALDYNABUF_CURRENT); #endif return 0; // ok } // try to read a file name for an input file. // library access by using <...> quoting is allowed. -// if library access is used, the library prefix will be added to the file name -// and TRUE will be stored via the "uses_lib" ptr. +// if library access is used, TRUE will be stored via the "uses_lib" ptr. // if library access is not used, FALSE will be stored via the "uses_lib" ptr. // The file name given in the assembler source code is converted from // UNIX style to platform style. @@ -654,27 +675,12 @@ static int read_filename_shared_end(int prefix_size) // input_skip_remainder() then. int input_read_input_filename(boolean *uses_lib) { - char *lib_prefix; // depends on platform - int prefix_size; // this much does not get platform-converted because it is already correct dynabuf_clear(GlobalDynaBuf); SKIPSPACE(); if (GotByte == '<') { // library access: *uses_lib = TRUE; - // read platform's lib prefix - lib_prefix = PLATFORM_LIBPREFIX; -#ifndef NO_NEED_FOR_ENV_VAR - // if lib prefix not set, complain - if (lib_prefix == NULL) { - Throw_error("\"ACME\" environment variable not found."); - return 1; // error - } -#endif - // copy lib path - dynabuf_add_string(GlobalDynaBuf, lib_prefix); - // remember border between optional library prefix and string from assembler source file - prefix_size = GlobalDynaBuf->size; // read file name string (must be a single string ) if (input_quoted_to_dynabuf('>')) return 1; // unterminated or escaping error @@ -683,7 +689,6 @@ int input_read_input_filename(boolean *uses_lib) } else { // "normal", non-library access: *uses_lib = FALSE; - prefix_size = 0; // no prefix in DynaBuf // old algo (do not merge with similar parts from "if" block!): if (GotByte != '"') { Throw_error("File name quotes not found (\"\" or <>)."); @@ -701,7 +706,7 @@ int input_read_input_filename(boolean *uses_lib) // see lines 416 and 1317 in pseudoopcodes.c for two more possible callers! } // check length, unescape, terminate, do platform conversion - return read_filename_shared_end(prefix_size); + return read_filename_shared_end(); } // try to read a file name for an output file. @@ -732,7 +737,7 @@ int input_read_output_filename(void) GetByte(); // eat terminator // check length, unescape, terminate, do platform conversion: - return read_filename_shared_end(0); // 0 -> there is no library prefix + return read_filename_shared_end(); } @@ -773,16 +778,63 @@ bits input_get_force_bit(void) } -// include path stuff - should be moved to its own file: +// "include path" stuff: -// ring list struct +static STRUCT_DYNABUF_REF(pathbuf, 256); // to combine search path and file spec + +// copy "default search path" from current file's file name into pathbuf: +static void default_path_to_pathbuf(void) +{ + const char *start = input_now->plat_pathref_filename, + *readptr, + *found; + + dynabuf_clear(pathbuf); + if (config.dialect >= V0_98__PATHS_AND_SYMBOLCHANGE) { + // scan filename for last directory separator + readptr = start; + found = NULL; + while (*readptr) { + if ((*readptr == DIRECTORY_SEPARATOR) + || (*readptr == ALTERNATIVE_DIR_SEP)) { + found = readptr; + } + ++readptr; + } + if (found) { + // +1 because we want the separator as well: + dynabuf_add_bytes(pathbuf, start, found - start + 1); + } + } else { + // do nothing - + // pathbuf is empty, which means "default search path" is "", + // which is exactly like it was in older versions. + } +} + +// copy platform-specific library search path into pathbuf: +static void library_path_to_pathbuf(void) +{ + char *lib_prefix; // depends on platform + + dynabuf_clear(pathbuf); + lib_prefix = PLATFORM_LIBPREFIX; + if ((PLATFORM_NEEDS_ENV_VAR) && (lib_prefix == NULL)) { + Throw_error("\"ACME\" environment variable not found."); + } else { + dynabuf_add_string(pathbuf, lib_prefix); + } +} + +// ring list struct for "include path items" struct ipi { struct ipi *next, *prev; const char *path; }; -static struct ipi ipi_head = {&ipi_head, &ipi_head, NULL}; // head element -static STRUCT_DYNABUF_REF(pathbuf, 256); // to combine search path and file spec + +// head element +static struct ipi ipi_head = {&ipi_head, &ipi_head, NULL}; // add entry void includepaths_add(const char *path) @@ -796,43 +848,64 @@ void includepaths_add(const char *path) 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, in platform style, and if wanted, with library prefix! + +// add filename (from GlobalDynaBuf) to pathbuf and try to open file: +static FILE *combine_and_open_ro(void) +{ + // if path does not end with directory separator, add one: + if (pathbuf->size + && (pathbuf->buffer[pathbuf->size - 1] != DIRECTORY_SEPARATOR) + && (pathbuf->buffer[pathbuf->size - 1] != ALTERNATIVE_DIR_SEP)) { + dynabuf_append(pathbuf, DIRECTORY_SEPARATOR); + } + // add file name + dynabuf_add_string(pathbuf, GLOBALDYNABUF_CURRENT); + // terminate + dynabuf_append(pathbuf, '\0'); + // try to open for reading + return fopen(pathbuf->buffer, FILE_READBINARY); +} + +// open file for reading +// "uses_lib" tells whether to use library prefix or to use search paths +// file name is expected in GlobalDynaBuf, in platform style and terminated +// returns NULL or open stream +// on success, GlobalDynaBuf contains full file name in platform style FILE *includepaths_open_ro(boolean 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 (uses_lib) { + // use library prefix + library_path_to_pathbuf(); + stream = combine_and_open_ro(); + } else { + // first try current default prefix + default_path_to_pathbuf(); + stream = combine_and_open_ro(); + if (stream == NULL) { + // default prefix failed, so try list entries: + for (ipi = ipi_head.next; ipi != &ipi_head; ipi = ipi->next) { + dynabuf_clear(pathbuf); + dynabuf_add_string(pathbuf, ipi->path); + stream = combine_and_open_ro(); + //printf("trying <<%s>> - ", pathbuf->buffer); + if (stream) { + //printf("ok\n"); + break; + } else { + //printf("failed\n"); + } } } } - if (stream == NULL) { + if (stream) { + // copy successful file name back to GlobalDynaBuf + dynabuf_clear(GlobalDynaBuf); + dynabuf_add_string(GlobalDynaBuf, pathbuf->buffer); + dynabuf_append(GlobalDynaBuf, '\0'); + } else { // CAUTION, I'm re-using the path dynabuf to assemble the error message: dynabuf_clear(pathbuf); dynabuf_add_string(pathbuf, "Cannot open input file \""); diff --git a/src/input.h b/src/input.h index 7980caf..09dfe97 100644 --- a/src/input.h +++ b/src/input.h @@ -31,6 +31,11 @@ enum inputsrc { INPUTSRC_RAM }; struct input { + const char *plat_pathref_filename; // file + // the filename *above* refers to the source file currently being parsed, which + // is needed as a reference for relative paths. + // the filename *below* (in "location") refers to the source file where + // the current code initially came from, i.e. it may change during macro execution. struct location location; // file + line (during RAM reads as well) enum inputsrc source; enum inputstate state; // state of input @@ -59,12 +64,12 @@ extern struct input *input_now; // current input structure // Prototypes -// let current input point to start of file +// parse a whole source code file // file name must be given in platform style, i.e. // "directory/basename.extension" on linux, // "directory.basename/extension" on RISC OS, etc. // and the pointer must remain valid forever! -extern void input_new_platform_file(const char *plat_filename, FILE *fd); +extern void input_parse_and_close_platform_file(const char *eternal_plat_filename, FILE *fd); // get next byte from currently active byte source in shortened high-level // format. When inside quotes, use input_quoted_to_dynabuf() instead! @@ -83,7 +88,7 @@ extern int input_quoted_to_dynabuf(char closing_quote); // process backslash escapes in GlobalDynaBuf (so size might shrink) // returns 1 on errors (escaping errors) -extern int input_unescape_dynabuf(int start_index); +extern int input_unescape_dynabuf(void); // Skip or store block (starting with next byte, so call directly after // reading opening brace). @@ -121,8 +126,7 @@ extern int input_read_and_lower_keyword(void); // try to read a file name for an input file. // library access by using <...> quoting is allowed. -// if library access is used, the library prefix will be added to the file name -// and TRUE will be stored via the "uses_lib" ptr. +// if library access is used, TRUE will be stored via the "uses_lib" ptr. // if library access is not used, FALSE will be stored via the "uses_lib" ptr. // The file name given in the assembler source code is converted from // UNIX style to platform style. @@ -151,14 +155,16 @@ extern int input_accept_comma(void); extern bits input_get_force_bit(void); -// include path stuff - should be moved to its own file: +// "include path" stuff: // 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, in platform style, and if wanted, with library prefix! +// open file for reading +// "uses_lib" tells whether to use library prefix or to use search paths +// file name is expected in GlobalDynaBuf, in platform style and terminated +// returns NULL or open stream +// on success, GlobalDynaBuf contains full file name in platform style extern FILE *includepaths_open_ro(boolean uses_lib); diff --git a/src/platform.c b/src/platform.c index f9155a4..963f484 100644 --- a/src/platform.c +++ b/src/platform.c @@ -1,5 +1,5 @@ // ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. -// Copyright (C) 1998-2016 Marco Baye +// Copyright (C) 1998-2024 Marco Baye // Have a look at "acme.c" for further info // // Platform specific stuff @@ -16,7 +16,7 @@ #endif // DOS, OS/2 and Windows -#if defined(__DJGPP__) || defined(__OS2__) || defined(__Windows__) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +#if defined(__DJGPP__) || defined(__OS2__) || defined(__Windows__) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) || defined(__MINGW32__) || defined(__MINGW64__) #include "_dos.c" #endif @@ -27,5 +27,36 @@ // add further platform files here -// Unix/Linux/others (surprisingly also works on at least some versions of Windows) +// Unix/Linux/others (also works on newer versions of Windows) +#ifndef platform_C #include "_std.c" +#endif + + +// stuff shared by some, but not all platforms: +#if PLATFORM_NEEDS_ENV_VAR + +#include // for getenv() +#include "dynabuf.h" + +// path of library tree, taken from env var +char *platform_lib_prefix = NULL; + +// function to setup pointer above +void platform_read_env_var(void) +{ + char *env_var; + + // Find out the path of ACME's library + env_var = getenv("ACME"); + // if environment variable was found, make a copy + if (env_var) { + dynabuf_clear(GlobalDynaBuf); + // copy environment variable to global dynamic buffer + dynabuf_add_string(GlobalDynaBuf, env_var); + dynabuf_append(GlobalDynaBuf, '\0'); // add terminator + platform_lib_prefix = dynabuf_get_copy(GlobalDynaBuf); + } +} + +#endif diff --git a/src/platform.h b/src/platform.h index 063ee66..541eb5b 100644 --- a/src/platform.h +++ b/src/platform.h @@ -1,5 +1,5 @@ // ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. -// Copyright (C) 1998-2016 Marco Baye +// Copyright (C) 1998-2024 Marco Baye // Have a look at "acme.c" for further info // // Platform specific stuff @@ -12,8 +12,8 @@ #endif // DOS, OS/2 and Windows -#if defined(__DJGPP__) || defined(__OS2__) || defined(__Windows__) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) -#define PLATFORM_VERSION "DOS/OS2/Win32 version. Compiled by Dirk Hoepfner" +#if defined(__DJGPP__) || defined(__OS2__) || defined(__Windows__) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) || defined(__MINGW32__) || defined(__MINGW64__) +#define PLATFORM_VERSION "DOS/OS2/Win32/Win64 version. Compiled by Dirk Hoepfner" #include "_dos.h" #endif @@ -25,8 +25,20 @@ // add further platform files here -// Unix/Linux/others (surprisingly also works on Windows) +// Unix/Linux/others (also works on newer versions of Windows) #ifndef PLATFORM_VERSION #define PLATFORM_VERSION "Platform independent version." -#endif #include "_std.h" +#endif + + +// stuff shared by some, but not all platforms: +#if PLATFORM_NEEDS_ENV_VAR + +// path to library tree, taken from env var: +extern char *platform_lib_prefix; + +// function to setup pointer above +extern void platform_read_env_var(void); + +#endif diff --git a/src/pseudoopcodes.c b/src/pseudoopcodes.c index bf55c05..7143c62 100644 --- a/src/pseudoopcodes.c +++ b/src/pseudoopcodes.c @@ -484,7 +484,7 @@ static enum eos encode_string(const struct encoder *inner_encoder, unsigned char // now convert to unescaped version // FIXME - next call does nothing because wanted