mirror of
https://github.com/uffejakobsen/acme.git
synced 2024-08-31 23:30:32 +00:00
search paths (given via -I) are now also displayed in error messages.
also prepared filespecs to be relative to current file in next version. git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@357 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
117aab0d6d
commit
640373c54f
@ -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.
|
||||
|
||||
|
||||
|
||||
|
11
src/_amiga.h
11
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)
|
||||
|
27
src/_dos.c
27
src/_dos.c
@ -7,33 +7,6 @@
|
||||
#define platform_C
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#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)
|
||||
{
|
||||
|
17
src/_dos.h
17
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);
|
||||
|
||||
|
@ -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!
|
||||
|
27
src/_std.c
27
src/_std.c
@ -7,31 +7,4 @@
|
||||
#define platform_C
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#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
|
||||
|
20
src/_std.h
20
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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
23
src/flow.c
23
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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
};
|
||||
|
213
src/input.c
213
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 = {
|
||||
"<none>", // file name for resolving paths
|
||||
{
|
||||
"<none>", // file name
|
||||
"<none>", // 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 <literal>)
|
||||
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 \"");
|
||||
|
24
src/input.h
24
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);
|
||||
|
||||
|
||||
|
@ -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 <stdlib.h> // 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
|
||||
|
@ -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
|
||||
|
@ -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<escaping!
|
||||
// FIXME - there is another block like this, scan for ROOSTA!
|
||||
if (input_unescape_dynabuf(0))
|
||||
if (input_unescape_dynabuf())
|
||||
return SKIP_REMAINDER; // escaping error
|
||||
|
||||
// send characters
|
||||
@ -928,8 +928,6 @@ static enum eos po_source(void) // now GotByte = illegal char
|
||||
FILE *stream;
|
||||
const char *eternal_plat_filename;
|
||||
char local_gotbyte;
|
||||
struct input new_input,
|
||||
*outer_input;
|
||||
|
||||
// enter new nesting level
|
||||
// quit program if recursion too deep
|
||||
@ -943,18 +941,9 @@ static enum eos po_source(void) // now GotByte = illegal char
|
||||
// if file could be opened, parse it. otherwise, complain
|
||||
stream = includepaths_open_ro(uses_lib);
|
||||
if (stream) {
|
||||
// GlobalDynaBuf contains either
|
||||
// library_prefix + platformstyle(source_argument) + '\0'
|
||||
// or
|
||||
// platformstyle(source_argument) + '\0'
|
||||
// it does _not_ contain any search path added using "-I", even if used!
|
||||
// if this is a problem, fix includepaths_open_ro()!
|
||||
eternal_plat_filename = dynabuf_get_copy(GlobalDynaBuf);
|
||||
outer_input = input_now; // remember old input
|
||||
local_gotbyte = GotByte; // CAUTION - ugly kluge
|
||||
input_now = &new_input; // activate new input
|
||||
flow_parse_and_close_platform_file(eternal_plat_filename, stream);
|
||||
input_now = outer_input; // restore previous input
|
||||
input_parse_and_close_platform_file(eternal_plat_filename, stream);
|
||||
GotByte = local_gotbyte; // CAUTION - ugly kluge
|
||||
}
|
||||
// leave nesting level
|
||||
@ -1388,7 +1377,7 @@ static enum eos throw_src_string(enum debuglevel level, const char prefix[])
|
||||
// now convert to unescaped version
|
||||
// FIXME - next call does nothing because wanted<escaping!
|
||||
// FIXME - there is another block like this, scan for ROOSTA!
|
||||
if (input_unescape_dynabuf(0))
|
||||
if (input_unescape_dynabuf())
|
||||
return SKIP_REMAINDER; // escaping error
|
||||
|
||||
dynabuf_append(GlobalDynaBuf, '\0'); // terminate string
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#define RELEASE "0.97" // update before release FIXME
|
||||
#define CODENAME "Zem" // update before release
|
||||
#define CHANGE_DATE "29 Feb" // update before release FIXME
|
||||
#define CHANGE_DATE "1 Mar" // update before release FIXME
|
||||
#define CHANGE_YEAR "2024" // update before release
|
||||
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/"
|
||||
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
|
||||
|
@ -9,12 +9,13 @@ all: dialects outformats
|
||||
echo "Testing cliargs: PASSED"
|
||||
echo
|
||||
|
||||
dialects: dialect085.a dialect086.a dialect09406.a dialect09408.a dialect09412.a
|
||||
dialects: dialect085.a dialect086.a dialect09406.a dialect09408.a dialect09412.a dialect097.a
|
||||
acme --strict --dialect 0.85 dialect085.a
|
||||
acme --strict --dialect 0.86 dialect086.a
|
||||
acme --strict --dialect 0.94.6 dialect09406.a
|
||||
acme --strict --dialect 0.94.8 dialect09408.a
|
||||
acme --strict --dialect 0.94.12 dialect09412.a
|
||||
acme --strict --dialect 0.97 dialect097.a
|
||||
$(RM) test.o
|
||||
|
||||
outformats: outformats.a outformats.sh outformat-*.exp
|
||||
|
@ -3,3 +3,5 @@
|
||||
; backslash becomes escape char in 0.97:
|
||||
b = "\"
|
||||
c = '\'
|
||||
|
||||
!src "dialect097.a"
|
||||
|
5
testing/cliargs/dialect097.a
Normal file
5
testing/cliargs/dialect097.a
Normal file
@ -0,0 +1,5 @@
|
||||
; 0.97 interprets all file names as relative to the initial directory:
|
||||
!src "subdir/sub1.inc"
|
||||
!if depth_given_in_included_file != 0 {
|
||||
!error "included wrong file."
|
||||
}
|
3
testing/cliargs/file2.inc
Normal file
3
testing/cliargs/file2.inc
Normal file
@ -0,0 +1,3 @@
|
||||
; 0.97 interprets all file names as relative to the initial directory,
|
||||
; so should include this file.
|
||||
depth_given_in_included_file = 0
|
3
testing/cliargs/subdir/file2.inc
Normal file
3
testing/cliargs/subdir/file2.inc
Normal file
@ -0,0 +1,3 @@
|
||||
; 0.97 interprets all file names as relative to the initial directory,
|
||||
; so shouldn't include this file.
|
||||
depth_given_in_included_file = 1
|
3
testing/cliargs/subdir/sub1.inc
Normal file
3
testing/cliargs/subdir/sub1.inc
Normal file
@ -0,0 +1,3 @@
|
||||
; 0.97 interprets all file names as relative to the initial directory,
|
||||
; so it looks for "file2" not in this directory, but one level up.
|
||||
!src "file2.inc"
|
Loading…
Reference in New Issue
Block a user