mirror of
https://github.com/uffejakobsen/acme.git
synced 2024-11-25 07:31:52 +00:00
improved "macro twice" error output and did some cleanup...
git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@355 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
45bb65d74d
commit
a2103c167e
@ -303,8 +303,8 @@ Loop var must be followed by either "in" keyword or comma.
|
|||||||
|
|
||||||
Macro already defined.
|
Macro already defined.
|
||||||
Macros can only be defined once. If you define a macro twice, ACME
|
Macros can only be defined once. If you define a macro twice, ACME
|
||||||
will help you find the definitions by giving a warning for the new
|
will help you find the definitions by giving a warning for the
|
||||||
definition and then an error for the earlier definition.
|
earlier definition and then an error for the new definition.
|
||||||
|
|
||||||
Macro not defined (or wrong signature).
|
Macro not defined (or wrong signature).
|
||||||
You tried to call a macro that either wasn't defined yet (always
|
You tried to call a macro that either wasn't defined yet (always
|
||||||
|
@ -90,13 +90,13 @@ void RISCOS_throwback(const char *message, int type)
|
|||||||
regs.r[0] = 0;
|
regs.r[0] = 0;
|
||||||
regs.r[1] = 0;
|
regs.r[1] = 0;
|
||||||
// regs.r[2] = (int) toplevel_source;
|
// regs.r[2] = (int) toplevel_source;
|
||||||
regs.r[2] = (int) input_now->location.filename;
|
regs.r[2] = (int) input_now->location.plat_filename;
|
||||||
_kernel_swi(XDDEUTILS_THROWBACKSEND, ®s, ®s);
|
_kernel_swi(XDDEUTILS_THROWBACKSEND, ®s, ®s);
|
||||||
}
|
}
|
||||||
// send throwback message
|
// send throwback message
|
||||||
regs.r[0] = 1;
|
regs.r[0] = 1;
|
||||||
regs.r[1] = 0;
|
regs.r[1] = 0;
|
||||||
regs.r[2] = (int) input_now->location.filename;
|
regs.r[2] = (int) input_now->location.plat_filename;
|
||||||
regs.r[3] = input_now->location.line_number;
|
regs.r[3] = input_now->location.line_number;
|
||||||
regs.r[4] = type;
|
regs.r[4] = type;
|
||||||
regs.r[5] = (int) message;
|
regs.r[5] = (int) message;
|
||||||
|
12
src/acme.c
12
src/acme.c
@ -78,7 +78,7 @@ static const char arg_vicelabels[] = "VICE labels filename";
|
|||||||
|
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
static const char **toplevel_sources;
|
static const char **toplevel_sources_plat; // source file names given on command line (platform-style)
|
||||||
static int toplevel_src_count = 0;
|
static int toplevel_src_count = 0;
|
||||||
|
|
||||||
|
|
||||||
@ -323,11 +323,11 @@ static void perform_pass(void)
|
|||||||
pass.warning_count = 0;
|
pass.warning_count = 0;
|
||||||
// Process toplevel files
|
// Process toplevel files
|
||||||
for (ii = 0; ii < toplevel_src_count; ++ii) {
|
for (ii = 0; ii < toplevel_src_count; ++ii) {
|
||||||
if ((fd = fopen(toplevel_sources[ii], FILE_READBINARY))) {
|
if ((fd = fopen(toplevel_sources_plat[ii], FILE_READBINARY))) {
|
||||||
flow_parse_and_close_file(fd, toplevel_sources[ii]);
|
flow_parse_and_close_platform_file(toplevel_sources_plat[ii], fd);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Error: Cannot open toplevel file \"%s\".\n", toplevel_sources[ii]);
|
fprintf(stderr, "Error: Cannot open toplevel file \"%s\".\n", toplevel_sources_plat[ii]);
|
||||||
if (toplevel_sources[ii][0] == '-')
|
if (toplevel_sources_plat[ii][0] == '-')
|
||||||
fprintf(stderr, "Options (starting with '-') must be given _before_ source files!\n");
|
fprintf(stderr, "Options (starting with '-') must be given _before_ source files!\n");
|
||||||
++pass.error_count;
|
++pass.error_count;
|
||||||
}
|
}
|
||||||
@ -725,7 +725,7 @@ int main(int argc, const char *argv[])
|
|||||||
// handle command line arguments
|
// handle command line arguments
|
||||||
cliargs_handle_options(short_option, long_option);
|
cliargs_handle_options(short_option, long_option);
|
||||||
// generate list of files to process
|
// generate list of files to process
|
||||||
cliargs_get_rest(&toplevel_src_count, &toplevel_sources, "No top level sources given");
|
cliargs_get_rest(&toplevel_src_count, &toplevel_sources_plat, "No top level sources given");
|
||||||
|
|
||||||
// now that we have processed all cli switches, check a few values for
|
// now that we have processed all cli switches, check a few values for
|
||||||
// valid range:
|
// valid range:
|
||||||
|
@ -23,7 +23,8 @@ typedef unsigned long uintval_t; // just for logical shift right
|
|||||||
|
|
||||||
// struct to remember where macros were defined (FIXME - use for symbols as well!)
|
// struct to remember where macros were defined (FIXME - use for symbols as well!)
|
||||||
struct location {
|
struct location {
|
||||||
const char *filename;
|
const char *plat_filename; // filename in platform style
|
||||||
|
// FIXME - add another field for filename in UNIX style? might be needed when fixing directory search order!
|
||||||
int line_number;
|
int line_number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
12
src/flow.c
12
src/flow.c
@ -267,17 +267,23 @@ void flow_do_while(struct do_while *loop)
|
|||||||
|
|
||||||
|
|
||||||
// parse a whole source code file
|
// parse a whole source code file
|
||||||
void flow_parse_and_close_file(FILE *fd, const char *filename)
|
// 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
|
// be verbose
|
||||||
if (config.process_verbosity > 2)
|
if (config.process_verbosity > 2)
|
||||||
printf("Parsing source file '%s'\n", filename);
|
printf("Parsing source file '%s'\n", plat_filename);
|
||||||
// set up new input
|
// set up new input
|
||||||
input_new_file(filename, fd);
|
input_new_platform_file(plat_filename, fd);
|
||||||
// parse block and check end reason
|
// parse block and check end reason
|
||||||
parse_until_eob_or_eof();
|
parse_until_eob_or_eof();
|
||||||
if (GotByte != CHAR_EOF)
|
if (GotByte != CHAR_EOF)
|
||||||
Throw_error("Found '}' instead of end-of-file.");
|
Throw_error("Found '}' instead of end-of-file.");
|
||||||
// close sublevel src
|
// 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);
|
fclose(input_now->src.fd);
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,11 @@ extern void flow_store_while_condition(struct condition *condition);
|
|||||||
extern void flow_do_while(struct do_while *loop);
|
extern void flow_do_while(struct do_while *loop);
|
||||||
|
|
||||||
// parse a whole source code file
|
// parse a whole source code file
|
||||||
extern void flow_parse_and_close_file(FILE *fd, const char *filename);
|
// 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
|
#endif
|
||||||
|
@ -444,13 +444,13 @@ static void throw_msg(const char *message, const char *ansicolor, const char *ty
|
|||||||
|
|
||||||
if (config.format_msvc) {
|
if (config.format_msvc) {
|
||||||
fprintf(config.msg_stream, "%s(%d) : %s%s%s (%s %s): %s\n",
|
fprintf(config.msg_stream, "%s(%d) : %s%s%s (%s %s): %s\n",
|
||||||
input_now->location.filename, input_now->location.line_number,
|
input_now->location.plat_filename, input_now->location.line_number,
|
||||||
ansicolor, type, resetcolor,
|
ansicolor, type, resetcolor,
|
||||||
section_now->type, section_now->title, message);
|
section_now->type, section_now->title, message);
|
||||||
} else {
|
} else {
|
||||||
fprintf(config.msg_stream, "%s%s%s - File %s, line %d (%s %s): %s\n",
|
fprintf(config.msg_stream, "%s%s%s - File %s, line %d (%s %s): %s\n",
|
||||||
ansicolor, type, resetcolor,
|
ansicolor, type, resetcolor,
|
||||||
input_now->location.filename, input_now->location.line_number,
|
input_now->location.plat_filename, input_now->location.line_number,
|
||||||
section_now->type, section_now->title, message);
|
section_now->type, section_now->title, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
29
src/input.c
29
src/input.c
@ -45,13 +45,18 @@ struct input *input_now = &outermost; // current input structure
|
|||||||
// functions
|
// functions
|
||||||
|
|
||||||
// let current input point to start of file
|
// let current input point to start of file
|
||||||
void input_new_file(const char *filename, FILE *fd)
|
// 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!
|
||||||
|
// 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)
|
||||||
{
|
{
|
||||||
input_now->location.filename = filename;
|
input_now->location.plat_filename = plat_filename;
|
||||||
input_now->location.line_number = 1;
|
input_now->location.line_number = 1;
|
||||||
input_now->source = INPUTSRC_FILE;
|
input_now->source = INPUTSRC_FILE;
|
||||||
input_now->state = INPUTSTATE_SOF;
|
input_now->state = INPUTSTATE_SOF;
|
||||||
input_now->src.fd = fd;
|
input_now->src.fd = fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -67,7 +72,7 @@ static void report_srcchar(char new_char)
|
|||||||
|
|
||||||
// if input has changed, insert explanation
|
// if input has changed, insert explanation
|
||||||
if (input_now != report->last_input) {
|
if (input_now != report->last_input) {
|
||||||
fprintf(report->fd, "\n; ******** Source: %s\n", input_now->location.filename);
|
fprintf(report->fd, "\n; ******** Source: %s\n", input_now->location.plat_filename); // actually, UNIX-style might be better than platform-style here...
|
||||||
report->last_input = input_now;
|
report->last_input = input_now;
|
||||||
report->asc_used = 0; // clear buffer
|
report->asc_used = 0; // clear buffer
|
||||||
prev_char = '\0';
|
prev_char = '\0';
|
||||||
@ -613,7 +618,7 @@ int input_read_and_lower_keyword(void)
|
|||||||
// shared ending when trying to read a file name.
|
// shared ending when trying to read a file name.
|
||||||
// The file name given in the assembler source code is converted from
|
// The file name given in the assembler source code is converted from
|
||||||
// UNIX style to platform style.
|
// UNIX style to platform style.
|
||||||
// Returns nonzero on error. Filename in GlobalDynaBuf.
|
// Returns nonzero on error. Filename in GlobalDynaBuf, including terminator.
|
||||||
// Errors are handled and reported, but caller should call
|
// Errors are handled and reported, but caller should call
|
||||||
// input_skip_remainder() then.
|
// input_skip_remainder() then.
|
||||||
static int read_filename_shared_end(int prefix_size)
|
static int read_filename_shared_end(int prefix_size)
|
||||||
@ -638,8 +643,10 @@ static int read_filename_shared_end(int prefix_size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try to read a file name for an input file.
|
// try to read a file name for an input file.
|
||||||
// library access by using <...> quoting is allowed. function will store info
|
// library access by using <...> quoting is allowed.
|
||||||
// about library usage at "uses_lib" ptr.
|
// 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 not used, FALSE will be stored via the "uses_lib" ptr.
|
||||||
// The file name given in the assembler source code is converted from
|
// The file name given in the assembler source code is converted from
|
||||||
// UNIX style to platform style.
|
// UNIX style to platform style.
|
||||||
// Returns nonzero on error. Filename in GlobalDynaBuf.
|
// Returns nonzero on error. Filename in GlobalDynaBuf.
|
||||||
@ -791,7 +798,7 @@ void includepaths_add(const char *path)
|
|||||||
}
|
}
|
||||||
// open file for reading (trying list entries as prefixes)
|
// open file for reading (trying list entries as prefixes)
|
||||||
// "uses_lib" tells whether to access library or to make use of include paths
|
// "uses_lib" tells whether to access library or to make use of include paths
|
||||||
// file name is expected in GlobalDynaBuf
|
// file name is expected in GlobalDynaBuf, in platform style, and if wanted, with library prefix!
|
||||||
FILE *includepaths_open_ro(boolean uses_lib)
|
FILE *includepaths_open_ro(boolean uses_lib)
|
||||||
{
|
{
|
||||||
FILE *stream;
|
FILE *stream;
|
||||||
|
14
src/input.h
14
src/input.h
@ -60,7 +60,11 @@ extern struct input *input_now; // current input structure
|
|||||||
// Prototypes
|
// Prototypes
|
||||||
|
|
||||||
// let current input point to start of file
|
// let current input point to start of file
|
||||||
extern void input_new_file(const char *filename, FILE *fd);
|
// 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);
|
||||||
|
|
||||||
// get next byte from currently active byte source in shortened high-level
|
// get next byte from currently active byte source in shortened high-level
|
||||||
// format. When inside quotes, use input_quoted_to_dynabuf() instead!
|
// format. When inside quotes, use input_quoted_to_dynabuf() instead!
|
||||||
@ -116,8 +120,10 @@ extern int input_read_keyword(void);
|
|||||||
extern int input_read_and_lower_keyword(void);
|
extern int input_read_and_lower_keyword(void);
|
||||||
|
|
||||||
// try to read a file name for an input file.
|
// try to read a file name for an input file.
|
||||||
// library access by using <...> quoting is allowed. function will store info
|
// library access by using <...> quoting is allowed.
|
||||||
// about library usage at "uses_lib" ptr.
|
// 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 not used, FALSE will be stored via the "uses_lib" ptr.
|
||||||
// The file name given in the assembler source code is converted from
|
// The file name given in the assembler source code is converted from
|
||||||
// UNIX style to platform style.
|
// UNIX style to platform style.
|
||||||
// Returns nonzero on error. Filename in GlobalDynaBuf.
|
// Returns nonzero on error. Filename in GlobalDynaBuf.
|
||||||
@ -152,7 +158,7 @@ extern void includepaths_add(const char *path);
|
|||||||
|
|
||||||
// open file for reading (trying list entries as prefixes)
|
// open file for reading (trying list entries as prefixes)
|
||||||
// "uses_lib" tells whether to access library or to make use of include paths
|
// "uses_lib" tells whether to access library or to make use of include paths
|
||||||
// file name is expected in GlobalDynaBuf
|
// file name is expected in GlobalDynaBuf, in platform style, and if wanted, with library prefix!
|
||||||
extern FILE *includepaths_open_ro(boolean uses_lib);
|
extern FILE *includepaths_open_ro(boolean uses_lib);
|
||||||
|
|
||||||
|
|
||||||
|
30
src/macro.c
30
src/macro.c
@ -77,7 +77,7 @@ static scope_t get_scope_and_title(void)
|
|||||||
// copy macro title to private dynabuf and add separator character
|
// copy macro title to private dynabuf and add separator character
|
||||||
dynabuf_clear(user_macro_name);
|
dynabuf_clear(user_macro_name);
|
||||||
dynabuf_add_string(user_macro_name, GLOBALDYNABUF_CURRENT);
|
dynabuf_add_string(user_macro_name, GLOBALDYNABUF_CURRENT);
|
||||||
dynabuf_append(user_macro_name, '\0');
|
dynabuf_append(user_macro_name, '\0'); // make sure terminator is part of buffer so get_copy() includes it!
|
||||||
dynabuf_clear(internal_name);
|
dynabuf_clear(internal_name);
|
||||||
dynabuf_add_string(internal_name, GLOBALDYNABUF_CURRENT);
|
dynabuf_add_string(internal_name, GLOBALDYNABUF_CURRENT);
|
||||||
dynabuf_append(internal_name, ARG_SEPARATOR);
|
dynabuf_append(internal_name, ARG_SEPARATOR);
|
||||||
@ -96,20 +96,6 @@ static int pipe_comma(void)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return malloc'd copy of string
|
|
||||||
// (yes, we could also use strdup() from <string.h>, but then we still would
|
|
||||||
// need to check for NULL etc.)
|
|
||||||
static char *get_string_copy(const char *original)
|
|
||||||
{
|
|
||||||
size_t size;
|
|
||||||
char *copy;
|
|
||||||
|
|
||||||
size = strlen(original) + 1;
|
|
||||||
copy = safe_malloc(size);
|
|
||||||
memcpy(copy, original, size);
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function is called from both macro definition and macro call.
|
// This function is called from both macro definition and macro call.
|
||||||
// Terminate macro name and copy from internal_name to GlobalDynaBuf
|
// Terminate macro name and copy from internal_name to GlobalDynaBuf
|
||||||
// (because that's where tree_hard_scan() looks for the search string).
|
// (because that's where tree_hard_scan() looks for the search string).
|
||||||
@ -135,8 +121,6 @@ static void report_redefinition(struct rwnode *macro_node)
|
|||||||
const char *buffered_section_type;
|
const char *buffered_section_type;
|
||||||
char *buffered_section_title;
|
char *buffered_section_title;
|
||||||
|
|
||||||
// show warning with location of current definition
|
|
||||||
Throw_warning(exception_macro_twice); // FIXME - throw as info?
|
|
||||||
// CAUTION, ugly kluge: fiddle with input_now and section_now
|
// CAUTION, ugly kluge: fiddle with input_now and section_now
|
||||||
// data to generate helpful error messages
|
// data to generate helpful error messages
|
||||||
// FIXME - move this to a function so "symbol twice" error can also use it
|
// FIXME - move this to a function so "symbol twice" error can also use it
|
||||||
@ -148,12 +132,15 @@ static void report_redefinition(struct rwnode *macro_node)
|
|||||||
input_now->location = original_macro->definition;
|
input_now->location = original_macro->definition;
|
||||||
section_now->type = "earlier";
|
section_now->type = "earlier";
|
||||||
section_now->title = "definition";
|
section_now->title = "definition";
|
||||||
// show error with location of earlier definition
|
// show warning with location of earlier definition
|
||||||
Throw_error(exception_macro_twice);
|
Throw_warning(exception_macro_twice); // FIXME - throw as info?
|
||||||
// restore old data
|
// restore old data
|
||||||
input_now->location = buffered_location;
|
input_now->location = buffered_location;
|
||||||
section_now->type = buffered_section_type;
|
section_now->type = buffered_section_type;
|
||||||
section_now->title = buffered_section_title;
|
section_now->title = buffered_section_title;
|
||||||
|
|
||||||
|
// show error with location of current definition
|
||||||
|
Throw_error(exception_macro_twice);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is only called during the first pass, so there's no need to
|
// This function is only called during the first pass, so there's no need to
|
||||||
@ -210,9 +197,8 @@ void macro_parse_definition(void) // Now GotByte = illegal char after "!macro"
|
|||||||
report_redefinition(macro_node);
|
report_redefinition(macro_node);
|
||||||
// Create new macro struct and set it up. Finally we'll read the body.
|
// Create new macro struct and set it up. Finally we'll read the body.
|
||||||
new_macro = safe_malloc(sizeof(*new_macro));
|
new_macro = safe_malloc(sizeof(*new_macro));
|
||||||
new_macro->definition.line_number = input_now->location.line_number;
|
new_macro->definition = input_now->location;
|
||||||
new_macro->definition.filename = get_string_copy(input_now->location.filename);
|
new_macro->original_name = dynabuf_get_copy(user_macro_name);
|
||||||
new_macro->original_name = get_string_copy(user_macro_name->buffer);
|
|
||||||
new_macro->parameter_list = formal_parameters;
|
new_macro->parameter_list = formal_parameters;
|
||||||
new_macro->body = input_skip_or_store_block(TRUE); // changes LineNumber
|
new_macro->body = input_skip_or_store_block(TRUE); // changes LineNumber
|
||||||
macro_node->body = new_macro; // link macro struct to tree node
|
macro_node->body = new_macro; // link macro struct to tree node
|
||||||
|
@ -368,9 +368,9 @@ static enum eos use_encoding_from_file(void)
|
|||||||
*buffered_table;
|
*buffered_table;
|
||||||
const struct encoder *buffered_encoder;
|
const struct encoder *buffered_encoder;
|
||||||
|
|
||||||
// read file name
|
// read file name and convert from UNIX style to platform style
|
||||||
if (input_read_input_filename(&uses_lib))
|
if (input_read_input_filename(&uses_lib))
|
||||||
return SKIP_REMAINDER; // missing or unterminated file name
|
return SKIP_REMAINDER; // if missing or unterminated, give up
|
||||||
|
|
||||||
// read from file
|
// read from file
|
||||||
stream = includepaths_open_ro(uses_lib);
|
stream = includepaths_open_ro(uses_lib);
|
||||||
@ -547,9 +547,9 @@ static enum eos po_binary(void)
|
|||||||
size.val.intval = -1; // means "not given" => "until EOF"
|
size.val.intval = -1; // means "not given" => "until EOF"
|
||||||
skip.val.intval = 0;
|
skip.val.intval = 0;
|
||||||
|
|
||||||
// if file name is missing, don't bother continuing
|
// read file name and convert from UNIX style to platform style
|
||||||
if (input_read_input_filename(&uses_lib))
|
if (input_read_input_filename(&uses_lib))
|
||||||
return SKIP_REMAINDER;
|
return SKIP_REMAINDER; // if missing or unterminated, give up
|
||||||
|
|
||||||
// try to open file
|
// try to open file
|
||||||
stream = includepaths_open_ro(uses_lib);
|
stream = includepaths_open_ro(uses_lib);
|
||||||
@ -926,6 +926,7 @@ static enum eos po_source(void) // now GotByte = illegal char
|
|||||||
{
|
{
|
||||||
boolean uses_lib;
|
boolean uses_lib;
|
||||||
FILE *stream;
|
FILE *stream;
|
||||||
|
const char *eternal_plat_filename;
|
||||||
char local_gotbyte;
|
char local_gotbyte;
|
||||||
struct input new_input,
|
struct input new_input,
|
||||||
*outer_input;
|
*outer_input;
|
||||||
@ -934,30 +935,27 @@ static enum eos po_source(void) // now GotByte = illegal char
|
|||||||
// quit program if recursion too deep
|
// quit program if recursion too deep
|
||||||
if (--sanity.source_recursions_left < 0)
|
if (--sanity.source_recursions_left < 0)
|
||||||
Throw_serious_error("Too deeply nested. Recursive \"!source\"?");
|
Throw_serious_error("Too deeply nested. Recursive \"!source\"?");
|
||||||
// read file name. quit function on error
|
|
||||||
|
// read file name and convert from UNIX style to platform style
|
||||||
if (input_read_input_filename(&uses_lib))
|
if (input_read_input_filename(&uses_lib))
|
||||||
return SKIP_REMAINDER;
|
return SKIP_REMAINDER; // if missing or unterminated, give up
|
||||||
|
|
||||||
// if file could be opened, parse it. otherwise, complain
|
// if file could be opened, parse it. otherwise, complain
|
||||||
stream = includepaths_open_ro(uses_lib);
|
stream = includepaths_open_ro(uses_lib);
|
||||||
if (stream) {
|
if (stream) {
|
||||||
// FIXME - just use safe_malloc and never free! this also saves us making a copy if defining macros down the road...
|
// GlobalDynaBuf contains either
|
||||||
#ifdef __GNUC__
|
// library_prefix + platformstyle(source_argument) + '\0'
|
||||||
char filename[GlobalDynaBuf->size]; // GCC can do this
|
// or
|
||||||
#else
|
// platformstyle(source_argument) + '\0'
|
||||||
char *filename = safe_malloc(GlobalDynaBuf->size); // VS can not
|
// it does _not_ contain any search path added using "-I", even if used!
|
||||||
#endif
|
// if this is a problem, fix includepaths_open_ro()!
|
||||||
|
eternal_plat_filename = dynabuf_get_copy(GlobalDynaBuf);
|
||||||
strcpy(filename, GLOBALDYNABUF_CURRENT);
|
|
||||||
outer_input = input_now; // remember old input
|
outer_input = input_now; // remember old input
|
||||||
local_gotbyte = GotByte; // CAUTION - ugly kluge
|
local_gotbyte = GotByte; // CAUTION - ugly kluge
|
||||||
input_now = &new_input; // activate new input
|
input_now = &new_input; // activate new input
|
||||||
flow_parse_and_close_file(stream, filename);
|
flow_parse_and_close_platform_file(eternal_plat_filename, stream);
|
||||||
input_now = outer_input; // restore previous input
|
input_now = outer_input; // restore previous input
|
||||||
GotByte = local_gotbyte; // CAUTION - ugly kluge
|
GotByte = local_gotbyte; // CAUTION - ugly kluge
|
||||||
#ifndef __GNUC__
|
|
||||||
free(filename); // GCC auto-frees
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
// leave nesting level
|
// leave nesting level
|
||||||
++sanity.source_recursions_left;
|
++sanity.source_recursions_left;
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#define RELEASE "0.97" // update before release FIXME
|
#define RELEASE "0.97" // update before release FIXME
|
||||||
#define CODENAME "Zem" // update before release
|
#define CODENAME "Zem" // update before release
|
||||||
#define CHANGE_DATE "27 Feb" // update before release FIXME
|
#define CHANGE_DATE "28 Feb" // update before release FIXME
|
||||||
#define CHANGE_YEAR "2024" // update before release
|
#define CHANGE_YEAR "2024" // update before release
|
||||||
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/"
|
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/"
|
||||||
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
|
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
|
||||||
|
7
testing/errors/alreadydefined.inc
Normal file
7
testing/errors/alreadydefined.inc
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
; this gets included by symboltwice*.a and macrotwice*.a
|
||||||
|
!macro m @arg {
|
||||||
|
nop
|
||||||
|
}
|
||||||
|
nop
|
||||||
|
label
|
||||||
|
nop
|
5
testing/errors/macrotwice1.a
Normal file
5
testing/errors/macrotwice1.a
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
*=$1000
|
||||||
|
!src "alreadydefined.inc"
|
||||||
|
!macro m @arg {
|
||||||
|
nop
|
||||||
|
}
|
5
testing/errors/macrotwice2.a
Normal file
5
testing/errors/macrotwice2.a
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
*=$1000
|
||||||
|
!macro m @arg {
|
||||||
|
nop
|
||||||
|
}
|
||||||
|
!src "alreadydefined.inc"
|
3
testing/errors/symboltwice1.a
Normal file
3
testing/errors/symboltwice1.a
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
*=$1000
|
||||||
|
!src "alreadydefined.inc"
|
||||||
|
label
|
3
testing/errors/symboltwice2.a
Normal file
3
testing/errors/symboltwice2.a
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
*=$1000
|
||||||
|
label
|
||||||
|
!src "alreadydefined.inc"
|
Loading…
Reference in New Issue
Block a user