added "--from-to" (and did some internal cleanup)
git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@334 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
		
							
								
								
									
										61
									
								
								src/acme.c
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								src/acme.c
									
									
									
									
									
								
							| @@ -54,6 +54,7 @@ static const char	arg_vicelabels[]	= "VICE labels filename"; | |||||||
| #define OPTION_VICELABELS	"vicelabels" | #define OPTION_VICELABELS	"vicelabels" | ||||||
| #define OPTION_REPORT		"report" | #define OPTION_REPORT		"report" | ||||||
| #define OPTION_SETPC		"setpc" | #define OPTION_SETPC		"setpc" | ||||||
|  | #define OPTION_FROM_TO		"from-to" | ||||||
| #define OPTION_CPU		"cpu" | #define OPTION_CPU		"cpu" | ||||||
| #define OPTION_INITMEM		"initmem" | #define OPTION_INITMEM		"initmem" | ||||||
| #define OPTION_MAXERRORS	"maxerrors" | #define OPTION_MAXERRORS	"maxerrors" | ||||||
| @@ -79,9 +80,6 @@ static const char	arg_vicelabels[]	= "VICE labels filename"; | |||||||
| // variables | // variables | ||||||
| static const char	**toplevel_sources; | static const char	**toplevel_sources; | ||||||
| static int		toplevel_src_count	= 0; | static int		toplevel_src_count	= 0; | ||||||
| #define ILLEGAL_START_ADDRESS	(-1) |  | ||||||
| static signed long	start_address		= ILLEGAL_START_ADDRESS; |  | ||||||
| static signed long	fill_value		= MEMINIT_USE_DEFAULT; |  | ||||||
| static const struct cpu_type	*default_cpu	= NULL; | static const struct cpu_type	*default_cpu	= NULL; | ||||||
| const char		*symbollist_filename	= NULL; | const char		*symbollist_filename	= NULL; | ||||||
| const char		*vicelabels_filename	= NULL; | const char		*vicelabels_filename	= NULL; | ||||||
| @@ -132,6 +130,7 @@ static void show_help_and_exit(void) | |||||||
| "      --" OPTION_LABELDUMP "           (old name for --" OPTION_SYMBOLLIST ")\n" | "      --" OPTION_LABELDUMP "           (old name for --" OPTION_SYMBOLLIST ")\n" | ||||||
| "      --" OPTION_VICELABELS " FILE     set file name for label dump in VICE format\n" | "      --" OPTION_VICELABELS " FILE     set file name for label dump in VICE format\n" | ||||||
| "      --" OPTION_SETPC " VALUE         set program counter\n" | "      --" OPTION_SETPC " VALUE         set program counter\n" | ||||||
|  | "      --" OPTION_FROM_TO " VALUE VALUE set start and end of output file\n" | ||||||
| "      --" OPTION_CPU " CPU             set target processor\n" | "      --" OPTION_CPU " CPU             set target processor\n" | ||||||
| "      --" OPTION_INITMEM " VALUE       define 'empty' memory\n" | "      --" OPTION_INITMEM " VALUE       define 'empty' memory\n" | ||||||
| "      --" OPTION_MAXERRORS " NUMBER    set number of errors before exiting\n" | "      --" OPTION_MAXERRORS " NUMBER    set number of errors before exiting\n" | ||||||
| @@ -256,8 +255,8 @@ static void perform_pass(void) | |||||||
| 	output_passinit();	// disable output, PC undefined | 	output_passinit();	// disable output, PC undefined | ||||||
| 	cputype_passinit(default_cpu);	// set default cpu type | 	cputype_passinit(default_cpu);	// set default cpu type | ||||||
| 	// if start address was given on command line, use it: | 	// if start address was given on command line, use it: | ||||||
| 	if (start_address != ILLEGAL_START_ADDRESS) | 	if (config.initial_pc != NO_VALUE_GIVEN) | ||||||
| 		vcpu_set_pc(start_address, 0); | 		vcpu_set_pc(config.initial_pc, 0);	// 0 -> no segment flags | ||||||
| 	encoding_passinit();	// set default encoding | 	encoding_passinit();	// set default encoding | ||||||
| 	section_passinit();	// set initial zone (untitled) | 	section_passinit();	// set initial zone (untitled) | ||||||
| 	// init variables | 	// init variables | ||||||
| @@ -419,30 +418,28 @@ static signed long string_to_number(const char *string) | |||||||
| 		could_not_parse(end); | 		could_not_parse(end); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  | // wrapper for fn above: complain about negative numbers | ||||||
|  | static signed long string_to_nonneg_number(const char *string) | ||||||
| // set program counter |  | ||||||
| static void set_starting_pc(const char expression[]) |  | ||||||
| { | { | ||||||
| 	start_address = string_to_number(expression); | 	signed long	result	= string_to_number(string); | ||||||
| 	if ((start_address > -1) && (start_address < 65536)) |  | ||||||
| 		return; |  | ||||||
|  |  | ||||||
| 	fprintf(stderr, "%sProgram counter out of range (0-0xffff).\n", cliargs_error); | 	if (result < 0) { | ||||||
|  | 		fprintf(stderr, "%sInvalid value, number is negative: '%s'.\n", cliargs_error, string); | ||||||
| 		exit(EXIT_FAILURE); | 		exit(EXIT_FAILURE); | ||||||
| 	} | 	} | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| // set initial memory contents | // set initial memory contents | ||||||
| static void set_mem_contents(const char expression[]) | static void set_mem_contents(const char expression[]) | ||||||
| { | { | ||||||
| 	fill_value = string_to_number(expression); | 	config.mem_init_value = string_to_number(expression); | ||||||
| 	if ((fill_value >= -128) && (fill_value <= 255)) | 	if ((config.mem_init_value < -128) || (config.mem_init_value > 255)) { | ||||||
| 		return; |  | ||||||
|  |  | ||||||
| 		fprintf(stderr, "%sInitmem value out of range (0-0xff).\n", cliargs_error); | 		fprintf(stderr, "%sInitmem value out of range (0-0xff).\n", cliargs_error); | ||||||
| 		exit(EXIT_FAILURE); | 		exit(EXIT_FAILURE); | ||||||
| 	} | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| // define symbol | // define symbol | ||||||
| @@ -533,8 +530,11 @@ static const char *long_option(const char *string) | |||||||
| 	else if (strcmp(string, OPTION_REPORT) == 0) | 	else if (strcmp(string, OPTION_REPORT) == 0) | ||||||
| 		report_filename = cliargs_safe_get_next(arg_reportfile); | 		report_filename = cliargs_safe_get_next(arg_reportfile); | ||||||
| 	else if (strcmp(string, OPTION_SETPC) == 0) | 	else if (strcmp(string, OPTION_SETPC) == 0) | ||||||
| 		set_starting_pc(cliargs_safe_get_next("program counter")); | 		config.initial_pc = string_to_nonneg_number(cliargs_safe_get_next("program counter")); | ||||||
| 	else if (strcmp(string, OPTION_CPU) == 0) | 	else if (strcmp(string, OPTION_FROM_TO) == 0) { | ||||||
|  | 		config.outfile_start = string_to_nonneg_number(cliargs_safe_get_next("start address of output file")); | ||||||
|  | 		config.outfile_end = string_to_nonneg_number(cliargs_safe_get_next("end address of output file")); | ||||||
|  | 	} else if (strcmp(string, OPTION_CPU) == 0) | ||||||
| 		set_starting_cpu(cliargs_get_next());	// NULL is ok (handled like unknown) | 		set_starting_cpu(cliargs_get_next());	// NULL is ok (handled like unknown) | ||||||
| 	else if (strcmp(string, OPTION_INITMEM) == 0) | 	else if (strcmp(string, OPTION_INITMEM) == 0) | ||||||
| 		set_mem_contents(cliargs_safe_get_next("initmem value")); | 		set_mem_contents(cliargs_safe_get_next("initmem value")); | ||||||
| @@ -563,6 +563,7 @@ static const char *long_option(const char *string) | |||||||
| 	else if (strcmp(string, OPTION_TEST) == 0) { | 	else if (strcmp(string, OPTION_TEST) == 0) { | ||||||
| 		config.wanted_version = VER_FUTURE; | 		config.wanted_version = VER_FUTURE; | ||||||
| 		config.test_new_features = TRUE; | 		config.test_new_features = TRUE; | ||||||
|  | 		config.outbuf_size = 0x1000000;	// 16 MiB (FIXME - give it its own cli switch!) | ||||||
| 	} PLATFORM_LONGOPTION_CODE | 	} PLATFORM_LONGOPTION_CODE | ||||||
| 	else if (strcmp(string, OPTION_COLOR) == 0) | 	else if (strcmp(string, OPTION_COLOR) == 0) | ||||||
| 		config.format_color = TRUE; | 		config.format_color = TRUE; | ||||||
| @@ -656,8 +657,28 @@ int main(int argc, const char *argv[]) | |||||||
| 	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, "No top level sources given"); | ||||||
|  |  | ||||||
|  | 	// now that we have processed all cli switches, check a few values for | ||||||
|  | 	// valid range: | ||||||
|  | 	if ((config.initial_pc != NO_VALUE_GIVEN) && (config.initial_pc >= config.outbuf_size)) { | ||||||
|  | 		fprintf(stderr, "%sProgram counter exceeds outbuffer size.\n", cliargs_error); | ||||||
|  | 		exit(EXIT_FAILURE); | ||||||
|  | 	} | ||||||
|  | 	if ((config.outfile_start != NO_VALUE_GIVEN) && (config.outfile_start >= config.outbuf_size)) { | ||||||
|  | 		fprintf(stderr, "%sStart address of output file exceeds outbuffer size.\n", cliargs_error); | ||||||
|  | 		exit(EXIT_FAILURE); | ||||||
|  | 	} | ||||||
|  | 	if ((config.outfile_end != NO_VALUE_GIVEN) && (config.outfile_end >= config.outbuf_size)) { | ||||||
|  | 		fprintf(stderr, "%sEnd address of output file exceeds outbuffer size.\n", cliargs_error); | ||||||
|  | 		exit(EXIT_FAILURE); | ||||||
|  | 	} | ||||||
|  | 	if (config.outfile_start > config.outfile_end) { | ||||||
|  | 		fprintf(stderr, "%sStart address of output file exceeds end address.\n", cliargs_error); | ||||||
|  | 		exit(EXIT_FAILURE); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// init output buffer | 	// init output buffer | ||||||
| 	output_createbuffer(fill_value, /* use_large_buf= */ config.test_new_features); | 	output_createbuffer(); | ||||||
| 	if (do_actual_work()) | 	if (do_actual_work()) | ||||||
| 		save_output_file(); | 		save_output_file(); | ||||||
| 	return ACME_finalize(EXIT_SUCCESS);	// dump labels, if wanted | 	return ACME_finalize(EXIT_SUCCESS);	// dump labels, if wanted | ||||||
|   | |||||||
| @@ -72,8 +72,6 @@ struct listitem { | |||||||
| // maximum nesting depth of "!src" and macro calls | // maximum nesting depth of "!src" and macro calls | ||||||
| // is not actually a limitation, but a means of finding recursions | // is not actually a limitation, but a means of finding recursions | ||||||
| #define MAX_NESTING	64 | #define MAX_NESTING	64 | ||||||
| // default value for output buffer |  | ||||||
| #define FILLVALUE_INITIAL	0 |  | ||||||
| // default value for "!fill" | // default value for "!fill" | ||||||
| #define FILLVALUE_FILL		0 | #define FILLVALUE_FILL		0 | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										38
									
								
								src/global.c
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								src/global.c
									
									
									
									
									
								
							| @@ -122,6 +122,11 @@ void config_default(struct config *conf) | |||||||
| 	conf->test_new_features		= FALSE;	// enabled by --test | 	conf->test_new_features		= FALSE;	// enabled by --test | ||||||
| 	conf->wanted_version		= VER_CURRENT;	// changed by --dialect | 	conf->wanted_version		= VER_CURRENT;	// changed by --dialect | ||||||
| 	conf->debuglevel		= DEBUGLEVEL_DEBUG;	// changed by --debuglevel, used by "!debug" | 	conf->debuglevel		= DEBUGLEVEL_DEBUG;	// changed by --debuglevel, used by "!debug" | ||||||
|  | 	conf->outbuf_size		= 0x10000;	// 64K, "--test" changes to 16M | ||||||
|  | 	conf->mem_init_value		= MEMINIT_USE_DEFAULT;	// set by --initmem | ||||||
|  | 	conf->initial_pc		= NO_VALUE_GIVEN;	// set by --setpc | ||||||
|  | 	conf->outfile_start		= NO_VALUE_GIVEN;	// set by --from-to | ||||||
|  | 	conf->outfile_end		= NO_VALUE_GIVEN;	// set by --from-to | ||||||
| } | } | ||||||
|  |  | ||||||
| // memory allocation stuff | // memory allocation stuff | ||||||
| @@ -164,8 +169,8 @@ boolean parser_change_nowarn_block_flag(boolean new_value) | |||||||
| 	return old_value; | 	return old_value; | ||||||
| } | } | ||||||
|  |  | ||||||
| #define SF_FOUND_BLANK		(1u << 0)	// statement had space or tab | #define SF_FOUND_BLANK		(1u << 0)	// statement started with space or tab | ||||||
| #define SF_IMPLIED_LABEL	(1u << 1)	// statement had implied label def | #define SF_FOUND_SYMBOL		(1u << 1)	// statement had label or symbol definition | ||||||
| #define SF_ADDR_PREFIX		(1u << 2)	// explicit symbol definition is an address | #define SF_ADDR_PREFIX		(1u << 2)	// explicit symbol definition is an address | ||||||
| #define SF_NOWARN_PREFIX	(1u << 3)	// suppress warnings for this statement | #define SF_NOWARN_PREFIX	(1u << 3)	// suppress warnings for this statement | ||||||
| static bits	statement_flags; | static bits	statement_flags; | ||||||
| @@ -181,15 +186,15 @@ extern void parser_set_nowarn_prefix(void) | |||||||
| 	statement_flags |= SF_NOWARN_PREFIX; | 	statement_flags |= SF_NOWARN_PREFIX; | ||||||
| } | } | ||||||
|  |  | ||||||
| // Check and return whether first label of statement. Complain if not. | // Check and return whether first symbol of statement. Complain if not. | ||||||
| static int first_label_of_statement(void) | static int first_symbol_of_statement(void) | ||||||
| { | { | ||||||
| 	if (statement_flags & SF_IMPLIED_LABEL) { | 	if (statement_flags & SF_FOUND_SYMBOL) { | ||||||
| 		Throw_error(exception_syntax); | 		Throw_error(exception_syntax); | ||||||
| 		input_skip_remainder(); | 		input_skip_remainder(); | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 	} | 	} | ||||||
| 	statement_flags |= SF_IMPLIED_LABEL;	// now there has been one | 	statement_flags |= SF_FOUND_SYMBOL;	// now there has been one | ||||||
| 	return TRUE; | 	return TRUE; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -270,21 +275,22 @@ static void parse_symbol_definition(scope_t scope) | |||||||
| // Parse global symbol definition or assembler mnemonic | // Parse global symbol definition or assembler mnemonic | ||||||
| static void parse_mnemo_or_global_symbol_def(void) | static void parse_mnemo_or_global_symbol_def(void) | ||||||
| { | { | ||||||
| 	boolean	is_mnemonic; | 	// read keyword and ask current cpu type if it's a mnemonic | ||||||
|  | 	if (CPU_state.type->keyword_is_mnemonic(input_read_keyword())) | ||||||
|  | 		return;	// statement has been handled | ||||||
|  |  | ||||||
|  | 	// if we're here, it wasn't a mnemonic, so it can only be a symbol name | ||||||
|  | 	if (!first_symbol_of_statement()) | ||||||
|  | 		return;	// more than one symbol, error has been reported | ||||||
|  |  | ||||||
| 	is_mnemonic = CPU_state.type->keyword_is_mnemonic(input_read_keyword()); |  | ||||||
| 	// It is only a label if it isn't a mnemonic |  | ||||||
| 	if ((!is_mnemonic) |  | ||||||
| 	&& first_label_of_statement()) { |  | ||||||
| 	// Now GotByte = illegal char | 	// Now GotByte = illegal char | ||||||
| 	// 04 Jun 2005: this fix should help to explain "strange" error messages. | 	// 04 Jun 2005: this fix should help to explain "strange" error messages. | ||||||
| 	// 17 May 2014: now it works for UTF-8 as well. | 	// 17 May 2014: now it works for UTF-8 as well. | ||||||
| 	if ((*GLOBALDYNABUF_CURRENT == (char) 0xa0) | 	if ((*GLOBALDYNABUF_CURRENT == (char) 0xa0) | ||||||
| 	|| ((GlobalDynaBuf->size >= 2) && (GLOBALDYNABUF_CURRENT[0] == (char) 0xc2) && (GLOBALDYNABUF_CURRENT[1] == (char) 0xa0))) | 	|| ((GlobalDynaBuf->size >= 2) && (GLOBALDYNABUF_CURRENT[0] == (char) 0xc2) && (GLOBALDYNABUF_CURRENT[1] == (char) 0xa0))) | ||||||
| 			Throw_first_pass_warning("Label name starts with a shift-space character."); | 		Throw_first_pass_warning("Symbol name starts with a shift-space character."); | ||||||
| 	parse_symbol_definition(SCOPE_GLOBAL); | 	parse_symbol_definition(SCOPE_GLOBAL); | ||||||
| } | } | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| // parse (cheap) local symbol definition | // parse (cheap) local symbol definition | ||||||
| @@ -292,7 +298,7 @@ static void parse_local_symbol_def(void) | |||||||
| { | { | ||||||
| 	scope_t	scope; | 	scope_t	scope; | ||||||
|  |  | ||||||
| 	if (!first_label_of_statement()) | 	if (!first_symbol_of_statement()) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	if (input_read_scope_and_symbol_name(&scope) == 0) | 	if (input_read_scope_and_symbol_name(&scope) == 0) | ||||||
| @@ -303,7 +309,7 @@ static void parse_local_symbol_def(void) | |||||||
| // parse anonymous backward label definition. Called with GotByte == '-' | // parse anonymous backward label definition. Called with GotByte == '-' | ||||||
| static void parse_backward_anon_def(void) | static void parse_backward_anon_def(void) | ||||||
| { | { | ||||||
| 	if (!first_label_of_statement()) | 	if (!first_symbol_of_statement()) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	dynabuf_clear(GlobalDynaBuf); | 	dynabuf_clear(GlobalDynaBuf); | ||||||
| @@ -319,7 +325,7 @@ static void parse_backward_anon_def(void) | |||||||
| // parse anonymous forward label definition. called with GotByte == ? | // parse anonymous forward label definition. called with GotByte == ? | ||||||
| static void parse_forward_anon_def(void) | static void parse_forward_anon_def(void) | ||||||
| { | { | ||||||
| 	if (!first_label_of_statement()) | 	if (!first_symbol_of_statement()) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	dynabuf_clear(GlobalDynaBuf); | 	dynabuf_clear(GlobalDynaBuf); | ||||||
|   | |||||||
| @@ -77,6 +77,13 @@ struct config { | |||||||
| 	boolean		test_new_features;	// FALSE, enabled by --test | 	boolean		test_new_features;	// FALSE, enabled by --test | ||||||
| 	enum version	wanted_version;	// set by --dialect (and --test --test) | 	enum version	wanted_version;	// set by --dialect (and --test --test) | ||||||
| 	signed long	debuglevel;	// set by --debuglevel, used by "!debug" | 	signed long	debuglevel;	// set by --debuglevel, used by "!debug" | ||||||
|  | 	signed long	outbuf_size;	// 64K, "--test" changes to 16M | ||||||
|  | #define MEMINIT_USE_DEFAULT	256	// default value for next field if cli switch not used: | ||||||
|  | 	signed long	mem_init_value;	// set by --initmem | ||||||
|  | #define NO_VALUE_GIVEN	(-1)	// default value for these fields if cli switch not used: | ||||||
|  | 	signed long	initial_pc;	// set by --setpc | ||||||
|  | 	signed long	outfile_start;	// set by --from-to | ||||||
|  | 	signed long	outfile_end;	// set by --from-to | ||||||
| }; | }; | ||||||
| extern struct config	config; | extern struct config	config; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										150
									
								
								src/input.c
									
									
									
									
									
								
							
							
						
						
									
										150
									
								
								src/input.c
									
									
									
									
									
								
							| @@ -339,12 +339,26 @@ static char GetQuotedByte(void) | |||||||
| } | } | ||||||
|  |  | ||||||
| // Skip remainder of statement, for example on error | // Skip remainder of statement, for example on error | ||||||
| // FIXME - check for quotes, otherwise this might treat a quoted colon like EOS! |  | ||||||
| void input_skip_remainder(void) | void input_skip_remainder(void) | ||||||
| { | { | ||||||
| 	while (GotByte) | 	while (GotByte) { | ||||||
| 		GetByte();	// Read characters until end-of-statement | 		GetByte();	// Read characters until end-of-statement | ||||||
| 	} | 	} | ||||||
|  | /* FIXME - check for quotes, otherwise this might treat a quoted colon like EOS! | ||||||
|  | this has already been a bug with "!to" and "!sl" where a workaround was implemented. | ||||||
|  | fix it here, once and for all, maybe like this: | ||||||
|  | 	dynabuf_clear(GlobalDynaBuf); | ||||||
|  | 	while (GotByte != CHAR_EOS) { | ||||||
|  | 		// check for quotes | ||||||
|  | 		if ((GotByte == '"') || (GotByte == '\'')) { | ||||||
|  | 			if (input_quoted_to_dynabuf(GotByte)) | ||||||
|  | 				break;	// error (CHAR_EOS before closing quote) | ||||||
|  | 		} | ||||||
|  | 		GetByte(); | ||||||
|  | 	} | ||||||
|  | 	dynabuf_clear(GlobalDynaBuf); | ||||||
|  | */ | ||||||
|  | } | ||||||
|  |  | ||||||
| // Ensure that the remainder of the current statement is empty, for example | // Ensure that the remainder of the current statement is empty, for example | ||||||
| // after mnemonics using implied addressing. | // after mnemonics using implied addressing. | ||||||
| @@ -599,33 +613,51 @@ int input_read_and_lower_keyword(void) | |||||||
| 	return length; | 	return length; | ||||||
| } | } | ||||||
|  |  | ||||||
| // Try to read a file name. | // shared ending when trying to read a file name. | ||||||
| // If "allow_library" is TRUE, library access by using <...> quoting |  | ||||||
| // is possible as well. If "uses_lib" is non-NULL, info about library |  | ||||||
| // usage is stored there. |  | ||||||
| // The file name given in the assembler source code is converted from | // 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. | ||||||
| // 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. | ||||||
| int input_read_filename(boolean allow_library, boolean *uses_lib) | static int read_filename_shared_end(int prefix_size) | ||||||
| { | { | ||||||
| 	int	start_of_string; | 	// check length | ||||||
| 	char	*lib_prefix, | 	if (GlobalDynaBuf->size == prefix_size) { | ||||||
| 		terminator; | 		Throw_error("No file name given."); | ||||||
|  |  | ||||||
| 	dynabuf_clear(GlobalDynaBuf); |  | ||||||
| 	SKIPSPACE(); |  | ||||||
| 	switch (GotByte) { |  | ||||||
| 	case '<':	// library access |  | ||||||
| 		if (uses_lib) |  | ||||||
| 			*uses_lib = TRUE; |  | ||||||
| 		// if library access forbidden, complain |  | ||||||
| 		if (!allow_library) { |  | ||||||
| 			Throw_error("Writing to library not supported."); |  | ||||||
| 		return 1;	// error | 		return 1;	// error | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// resolve backslash escapes | ||||||
|  | 	if (input_unescape_dynabuf(prefix_size)) | ||||||
|  | 		return 1;	// escaping error | ||||||
|  |  | ||||||
|  | 	// terminate string | ||||||
|  | 	dynabuf_append(GlobalDynaBuf, '\0'); | ||||||
|  | #ifdef PLATFORM_CONVERTPATH | ||||||
|  | 	// platform-specific path name conversion | ||||||
|  | 	PLATFORM_CONVERTPATH(GLOBALDYNABUF_CURRENT + prefix_size); | ||||||
|  | #endif | ||||||
|  | 	return 0;	// ok | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // try to read a file name for an input file. | ||||||
|  | // library access by using <...> quoting is allowed. function will store info | ||||||
|  | // about library usage at "uses_lib" ptr. | ||||||
|  | // The file name given in the assembler source code is converted from | ||||||
|  | // UNIX style to platform style. | ||||||
|  | // Returns nonzero on error. Filename in GlobalDynaBuf. | ||||||
|  | // Errors are handled and reported, but caller should call | ||||||
|  | // 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 | 		// read platform's lib prefix | ||||||
| 		lib_prefix = PLATFORM_LIBPREFIX; | 		lib_prefix = PLATFORM_LIBPREFIX; | ||||||
| #ifndef NO_NEED_FOR_ENV_VAR | #ifndef NO_NEED_FOR_ENV_VAR | ||||||
| @@ -635,44 +667,70 @@ int input_read_filename(boolean allow_library, boolean *uses_lib) | |||||||
| 			return 1;	// error | 			return 1;	// error | ||||||
| 		} | 		} | ||||||
| #endif | #endif | ||||||
| 		// copy lib path and set quoting char | 		// copy lib path | ||||||
| 		dynabuf_add_string(GlobalDynaBuf, lib_prefix); | 		dynabuf_add_string(GlobalDynaBuf, lib_prefix); | ||||||
| 		terminator = '>'; | 		// remember border between optional library prefix and string from assembler source file | ||||||
| 		break; | 		prefix_size = GlobalDynaBuf->size; | ||||||
| 	case '"':	// normal access | 		// read file name string (must be a single string <literal>) | ||||||
| 		if (uses_lib) | 		if (input_quoted_to_dynabuf('>')) | ||||||
|  | 			return 1;	// unterminated or escaping error | ||||||
|  |  | ||||||
|  | 		GetByte();	// eat '>' terminator | ||||||
|  | 	} else { | ||||||
|  | 		// "normal", non-library access: | ||||||
| 		*uses_lib = FALSE; | 		*uses_lib = FALSE; | ||||||
| 		terminator = '"'; | 		prefix_size = 0;	// no prefix in DynaBuf | ||||||
| 		break; | // old algo (do not merge with similar parts from "if" block!): | ||||||
| 	default:	// none of the above | 		if (GotByte != '"') { | ||||||
| 			Throw_error("File name quotes not found (\"\" or <>)."); | 			Throw_error("File name quotes not found (\"\" or <>)."); | ||||||
| 			return 1;	// error | 			return 1;	// error | ||||||
| 		} | 		} | ||||||
| 	// remember border between optional library prefix and string from assembler source file |  | ||||||
| 	start_of_string = GlobalDynaBuf->size; |  | ||||||
| 		// read file name string | 		// read file name string | ||||||
| 	if (input_quoted_to_dynabuf(terminator)) | 		if (input_quoted_to_dynabuf('"')) | ||||||
| 			return 1;	// unterminated or escaping error | 			return 1;	// unterminated or escaping error | ||||||
|  |  | ||||||
| 		GetByte();	// eat terminator | 		GetByte();	// eat terminator | ||||||
| 	// check length | // new algo: | ||||||
| 	if (GlobalDynaBuf->size == start_of_string) { | // it should be possible to construct the name of input file from symbols, so | ||||||
| 		Throw_error("No file name given."); | // build environments can define a name at one place and use it at another. | ||||||
|  | // FIXME - use expression parser to read filename string! | ||||||
|  | // 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); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // try to read a file name for an output file. | ||||||
|  | // library access by using <...> quoting is forbidden. | ||||||
|  | // The file name given in the assembler source code is converted from | ||||||
|  | // UNIX style to platform style. | ||||||
|  | // Returns nonzero on error. Filename in GlobalDynaBuf. | ||||||
|  | // Errors are handled and reported, but caller should call | ||||||
|  | // input_skip_remainder() then. | ||||||
|  | // | ||||||
|  | // this is only used for "!to" and "!sl", i.e. output file names. these | ||||||
|  | // must be given as a literal string, and it should be kept this way. | ||||||
|  | int input_read_output_filename(void) | ||||||
|  | { | ||||||
|  | 	SKIPSPACE(); | ||||||
|  | 	if (GotByte == '<') { | ||||||
|  | 		Throw_error("Writing to library not supported."); | ||||||
| 		return 1;	// error | 		return 1;	// error | ||||||
| 	} | 	} | ||||||
|  | 	if (GotByte != '"') { | ||||||
| 	// resolve backslash escapes | 		Throw_error("File name quotes not found (\"\")."); | ||||||
| 	if (input_unescape_dynabuf(start_of_string)) | 		return 1;	// error | ||||||
| 		return 1;	// escaping error |  | ||||||
|  |  | ||||||
| 	// terminate string |  | ||||||
| 	dynabuf_append(GlobalDynaBuf, '\0'); |  | ||||||
| #ifdef PLATFORM_CONVERTPATH |  | ||||||
| 	// platform-specific path name conversion |  | ||||||
| 	PLATFORM_CONVERTPATH(GLOBALDYNABUF_CURRENT + start_of_string); |  | ||||||
| #endif |  | ||||||
| 	return 0;	// ok |  | ||||||
| 	} | 	} | ||||||
|  | 	dynabuf_clear(GlobalDynaBuf); | ||||||
|  | 	// read file name string (must be a single string literal! do not change this!) | ||||||
|  | 	if (input_quoted_to_dynabuf('"')) | ||||||
|  | 		return 1;	// unterminated or escaping error | ||||||
|  |  | ||||||
|  | 	GetByte();	// eat terminator | ||||||
|  | 	// check length, unescape, terminate, do platform conversion: | ||||||
|  | 	return read_filename_shared_end(0);	// 0 -> there is no library prefix | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| // Try to read a comma, skipping spaces before and after. Return TRUE if comma | // Try to read a comma, skipping spaces before and after. Return TRUE if comma | ||||||
| // found, otherwise FALSE. | // found, otherwise FALSE. | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								src/input.h
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								src/input.h
									
									
									
									
									
								
							| @@ -116,16 +116,24 @@ extern int input_read_keyword(void); | |||||||
| // Zero lengths will produce a "missing string" error. | // Zero lengths will produce a "missing string" error. | ||||||
| extern int input_read_and_lower_keyword(void); | extern int input_read_and_lower_keyword(void); | ||||||
|  |  | ||||||
| // Try to read a file name. | // try to read a file name for an input file. | ||||||
| // If "allow_library" is TRUE, library access by using <...> quoting | // library access by using <...> quoting is allowed. function will store info | ||||||
| // is possible as well. If "uses_lib" is non-NULL, info about library | // about library usage at "uses_lib" ptr. | ||||||
| // usage is stored there. |  | ||||||
| // 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. | ||||||
| // 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. | ||||||
| extern int input_read_filename(boolean library_allowed, boolean *uses_lib); | extern int input_read_input_filename(boolean *uses_lib); | ||||||
|  |  | ||||||
|  | // try to read a file name for an output file ("!to" and "!sl" only). | ||||||
|  | // library access by using <...> quoting is forbidden. | ||||||
|  | // The file name given in the assembler source code is converted from | ||||||
|  | // UNIX style to platform style. | ||||||
|  | // Returns nonzero on error. Filename in GlobalDynaBuf. | ||||||
|  | // Errors are handled and reported, but caller should call | ||||||
|  | // input_skip_remainder() then. | ||||||
|  | extern int input_read_output_filename(void); | ||||||
|  |  | ||||||
| // Try to read a comma, skipping spaces before and after. Return TRUE if comma | // Try to read a comma, skipping spaces before and after. Return TRUE if comma | ||||||
| // found, otherwise FALSE. | // found, otherwise FALSE. | ||||||
|   | |||||||
							
								
								
									
										57
									
								
								src/output.c
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								src/output.c
									
									
									
									
									
								
							| @@ -38,8 +38,7 @@ struct segment { | |||||||
| // structure for all output stuff: | // structure for all output stuff: | ||||||
| struct output { | struct output { | ||||||
| 	// output buffer stuff | 	// output buffer stuff | ||||||
| 	intval_t	bufsize;	// either 64 KiB or 16 MiB | 	char		*buffer;	// holds assembled code (size is config.outbuf_size) | ||||||
| 	char		*buffer;	// holds assembled code |  | ||||||
| 	intval_t	write_idx;	// index of next write | 	intval_t	write_idx;	// index of next write | ||||||
| 	intval_t	lowest_written;		// smallest address used | 	intval_t	lowest_written;		// smallest address used | ||||||
| 	intval_t	highest_written;	// largest address used | 	intval_t	highest_written;	// largest address used | ||||||
| @@ -111,7 +110,7 @@ static void find_segment_max(intval_t new_pc) | |||||||
| 	while (test_segment->start <= new_pc) | 	while (test_segment->start <= new_pc) | ||||||
| 		test_segment = test_segment->next; | 		test_segment = test_segment->next; | ||||||
| 	if (test_segment == &out->segment.list_head) | 	if (test_segment == &out->segment.list_head) | ||||||
| 		out->segment.max = out->bufsize - 1; | 		out->segment.max = config.outbuf_size - 1; | ||||||
| 	else | 	else | ||||||
| 		out->segment.max = test_segment->start - 1;	// last free address available | 		out->segment.max = test_segment->start - 1;	// last free address available | ||||||
| } | } | ||||||
| @@ -120,7 +119,7 @@ static void find_segment_max(intval_t new_pc) | |||||||
| // | // | ||||||
| static void border_crossed(int current_offset) | static void border_crossed(int current_offset) | ||||||
| { | { | ||||||
| 	if (current_offset >= out->bufsize) | 	if (current_offset >= config.outbuf_size) | ||||||
| 		Throw_serious_error("Produced too much code."); | 		Throw_serious_error("Produced too much code."); | ||||||
| 	// TODO - get rid of FIRST_PASS condition, because user can suppress these warnings if they want | 	// TODO - get rid of FIRST_PASS condition, because user can suppress these warnings if they want | ||||||
| 	if (FIRST_PASS) { | 	if (FIRST_PASS) { | ||||||
| @@ -206,7 +205,7 @@ void output_skip(int size) | |||||||
| // fill output buffer with given byte value | // fill output buffer with given byte value | ||||||
| static void fill_completely(char value) | static void fill_completely(char value) | ||||||
| { | { | ||||||
| 	memset(out->buffer, value, out->bufsize); | 	memset(out->buffer, value, config.outbuf_size); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -276,42 +275,54 @@ int outputfile_set_filename(void) | |||||||
|  |  | ||||||
|  |  | ||||||
| // init output struct (done later) | // init output struct (done later) | ||||||
| void output_createbuffer(signed long fill_value, boolean use_large_buf) | void output_createbuffer(void) | ||||||
| { | { | ||||||
| 	out->bufsize = use_large_buf ? 0x1000000 : 0x10000; | 	char	fill_value	= 0;	// default value for output buffer | ||||||
| 	out->buffer = safe_malloc(out->bufsize); |  | ||||||
| 	if (fill_value == MEMINIT_USE_DEFAULT) { | 	out->buffer = safe_malloc(config.outbuf_size); | ||||||
| 		fill_value = FILLVALUE_INITIAL; | 	if (config.mem_init_value == MEMINIT_USE_DEFAULT) { | ||||||
| 		out->initvalue_set = FALSE; | 		out->initvalue_set = FALSE;	// "!initmem" can be used | ||||||
| 	} else { | 	} else { | ||||||
| 		out->initvalue_set = TRUE; | 		out->initvalue_set = TRUE;	// "!initmem" generates a warning | ||||||
|  | 		fill_value = 0xff & config.mem_init_value; | ||||||
| 	} | 	} | ||||||
| 	// init output buffer (fill memory with initial value) | 	// init output buffer (fill memory with initial value) | ||||||
| 	fill_completely(fill_value & 0xff); | 	fill_completely(fill_value); | ||||||
| 	// init ring list of segments | 	// init ring list of segments | ||||||
| 	out->segment.list_head.next = &out->segment.list_head; | 	out->segment.list_head.next = &out->segment.list_head; | ||||||
| 	out->segment.list_head.prev = &out->segment.list_head; | 	out->segment.list_head.prev = &out->segment.list_head; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| // dump used portion of output buffer into output file | // write used portion of output buffer to output file | ||||||
| void output_save_file(FILE *fd) | void output_save_file(FILE *fd) | ||||||
| { | { | ||||||
| 	intval_t	start, | 	intval_t	start, | ||||||
|  | 			end, | ||||||
| 			amount; | 			amount; | ||||||
|  |  | ||||||
| 	if (out->highest_written < out->lowest_written) { | 	start = out->lowest_written; | ||||||
|  | 	end = out->highest_written; | ||||||
|  | 	// if cli args were given, they override the actual values: | ||||||
|  | 	if (config.outfile_start != NO_VALUE_GIVEN) | ||||||
|  | 		start = config.outfile_start; | ||||||
|  | 	if (config.outfile_end != NO_VALUE_GIVEN) | ||||||
|  | 		end = config.outfile_end; | ||||||
|  |  | ||||||
|  | 	if (end < start) { | ||||||
| 		// nothing written | 		// nothing written | ||||||
| 		start = 0;	// I could try to use some segment start, but what for? | 		start = 0;	// I could try to use some segment start, but what for? | ||||||
| 		amount = 0; | 		amount = 0; | ||||||
|  | 		// FIXME - how about not writing anything in this case? | ||||||
|  | 		// a CBM file would consist of a bogus load address and nothing else! | ||||||
| 	} else { | 	} else { | ||||||
| 		start = out->lowest_written; | 		amount = end - start + 1; | ||||||
| 		amount = out->highest_written - start + 1; |  | ||||||
| 	} | 	} | ||||||
| 	if (config.process_verbosity) | 	if (config.process_verbosity) | ||||||
| 		printf("Saving %ld (0x%lx) bytes (0x%lx - 0x%lx exclusive).\n", | 		printf("Saving %ld (0x%lx) bytes (0x%lx - 0x%lx exclusive).\n", | ||||||
| 			amount, amount, start, start + amount); | 			amount, amount, start, start + amount); | ||||||
| 	// output file header according to file format | 	// output file header according to file format | ||||||
|  | 	// FIXME - add checks and error messages for "start is above $ffff"!) | ||||||
| 	switch (output_format) { | 	switch (output_format) { | ||||||
| 	case OUTPUT_FORMAT_APPLE: | 	case OUTPUT_FORMAT_APPLE: | ||||||
| 		PLATFORM_SETFILETYPE_APPLE(output_filename); | 		PLATFORM_SETFILETYPE_APPLE(output_filename); | ||||||
| @@ -402,13 +413,13 @@ void output_passinit(void) | |||||||
| //	} | //	} | ||||||
|  |  | ||||||
| 	// invalidate start and end (first byte actually written will fix them) | 	// invalidate start and end (first byte actually written will fix them) | ||||||
| 	out->lowest_written = out->bufsize - 1; | 	out->lowest_written = config.outbuf_size - 1; | ||||||
| 	out->highest_written = 0; | 	out->highest_written = 0; | ||||||
| 	// deactivate output - any byte written will trigger error: | 	// deactivate output - any byte written will trigger error: | ||||||
| 	output_byte = no_output; | 	output_byte = no_output; | ||||||
| 	out->write_idx = 0;	// same as pc on pass init! | 	out->write_idx = 0;	// same as pc on pass init! | ||||||
| 	out->segment.start = NO_SEGMENT_START;	// TODO - "no active segment" could be made a segment flag! | 	out->segment.start = NO_SEGMENT_START;	// TODO - "no active segment" could be made a segment flag! | ||||||
| 	out->segment.max = out->bufsize - 1;	// TODO - use end of bank? | 	out->segment.max = config.outbuf_size - 1;	// TODO - use end of bank? | ||||||
| 	out->segment.flags = 0; | 	out->segment.flags = 0; | ||||||
| 	out->xor = 0; | 	out->xor = 0; | ||||||
|  |  | ||||||
| @@ -467,7 +478,7 @@ void output_start_segment(intval_t address_change, bits segment_flags) | |||||||
| 	output_end_segment(); | 	output_end_segment(); | ||||||
|  |  | ||||||
| 	// calculate start of new segment | 	// calculate start of new segment | ||||||
| 	out->write_idx = (out->write_idx + address_change) & (out->bufsize - 1); | 	out->write_idx = (out->write_idx + address_change) & (config.outbuf_size - 1); | ||||||
| 	out->segment.start = out->write_idx; | 	out->segment.start = out->write_idx; | ||||||
| 	out->segment.flags = segment_flags; | 	out->segment.flags = segment_flags; | ||||||
| 	// allow writing to output buffer | 	// allow writing to output buffer | ||||||
| @@ -568,7 +579,7 @@ int vcpu_get_statement_size(void) | |||||||
| // adjust program counter (called at end of each statement) | // adjust program counter (called at end of each statement) | ||||||
| void vcpu_end_statement(void) | void vcpu_end_statement(void) | ||||||
| { | { | ||||||
| 	CPU_state.pc.val.intval = (CPU_state.pc.val.intval + CPU_state.add_to_pc) & (out->bufsize - 1); | 	CPU_state.pc.val.intval = (CPU_state.pc.val.intval + CPU_state.add_to_pc) & (config.outbuf_size - 1); | ||||||
| 	CPU_state.add_to_pc = 0; | 	CPU_state.add_to_pc = 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -607,7 +618,7 @@ void pseudopc_end(void) | |||||||
| 		if (config.wanted_version >= VER_DISABLED_OBSOLETE_STUFF) | 		if (config.wanted_version >= VER_DISABLED_OBSOLETE_STUFF) | ||||||
| 			BUG("ClosingUnopenedPseudopcBlock", 0); | 			BUG("ClosingUnopenedPseudopcBlock", 0); | ||||||
| 	} else { | 	} else { | ||||||
| 		CPU_state.pc.val.intval = (CPU_state.pc.val.intval - pseudopc_current_context->offset) & (out->bufsize - 1);	// pc might have wrapped around | 		CPU_state.pc.val.intval = (CPU_state.pc.val.intval - pseudopc_current_context->offset) & (config.outbuf_size - 1);	// pc might have wrapped around | ||||||
| 		CPU_state.pc.ntype = pseudopc_current_context->ntype; | 		CPU_state.pc.ntype = pseudopc_current_context->ntype; | ||||||
| 		pseudopc_current_context = pseudopc_current_context->outer;	// go back to outer block | 		pseudopc_current_context = pseudopc_current_context->outer;	// go back to outer block | ||||||
| 	} | 	} | ||||||
| @@ -631,7 +642,7 @@ int pseudopc_unpseudo(struct number *target, struct pseudopc *context, unsigned | |||||||
| 			return 1;	// error | 			return 1;	// error | ||||||
| 		} | 		} | ||||||
| 		// FIXME - in future, check both target and context for NUMTYPE_UNDEFINED! | 		// FIXME - in future, check both target and context for NUMTYPE_UNDEFINED! | ||||||
| 		target->val.intval = (target->val.intval - context->offset) & (out->bufsize - 1);	// FIXME - is masking really needed?	TODO | 		target->val.intval = (target->val.intval - context->offset) & (config.outbuf_size - 1);	// FIXME - is masking really needed?	TODO | ||||||
| 		context = context->outer; | 		context = context->outer; | ||||||
| 	} | 	} | ||||||
| 	return 0;	// ok | 	return 0;	// ok | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
| // constants | // constants | ||||||
| #define MEMINIT_USE_DEFAULT	256 |  | ||||||
| // segment flags | // segment flags | ||||||
| #define	SEGMENT_FLAG_OVERLAY	(1u << 0)	// do not warn about this segment overwriting another one | #define	SEGMENT_FLAG_OVERLAY	(1u << 0)	// do not warn about this segment overwriting another one | ||||||
| #define	SEGMENT_FLAG_INVISIBLE	(1u << 1)	// do not warn about other segments overwriting this one | #define	SEGMENT_FLAG_INVISIBLE	(1u << 1)	// do not warn about other segments overwriting this one | ||||||
| @@ -43,7 +43,7 @@ extern void output_passinit(void); | |||||||
| // outbuf stuff: | // outbuf stuff: | ||||||
|  |  | ||||||
| // alloc and init mem buffer (done later) | // alloc and init mem buffer (done later) | ||||||
| extern void output_createbuffer(signed long fill_value, boolean use_large_buf); | extern void output_createbuffer(void); | ||||||
|  |  | ||||||
| // skip over some bytes in output buffer without starting a new segment | // skip over some bytes in output buffer without starting a new segment | ||||||
| // (used by "!skip", and also called by "!binary" if really calling | // (used by "!skip", and also called by "!binary" if really calling | ||||||
| @@ -72,7 +72,7 @@ extern int outputfile_prefer_cbm_format(void); | |||||||
| // try to set output file name held in DynaBuf. Returns zero on success. | // try to set output file name held in DynaBuf. Returns zero on success. | ||||||
| extern int outputfile_set_filename(void); | extern int outputfile_set_filename(void); | ||||||
|  |  | ||||||
| // write smallest-possible part of memory buffer to file | // write used portion of output buffer to output file | ||||||
| extern void output_save_file(FILE *fd); | extern void output_save_file(FILE *fd); | ||||||
|  |  | ||||||
| // change output pointer and enable output | // change output pointer and enable output | ||||||
|   | |||||||
| @@ -136,7 +136,7 @@ static enum eos po_to(void) | |||||||
|  |  | ||||||
| 	// read filename to global dynamic buffer | 	// read filename to global dynamic buffer | ||||||
| 	// if no file name given, exit (complaining will have been done) | 	// if no file name given, exit (complaining will have been done) | ||||||
| 	if (input_read_filename(FALSE, NULL)) | 	if (input_read_output_filename()) | ||||||
| 		return SKIP_REMAINDER; | 		return SKIP_REMAINDER; | ||||||
|  |  | ||||||
| 	// only act upon this pseudo opcode in first pass | 	// only act upon this pseudo opcode in first pass | ||||||
| @@ -360,6 +360,15 @@ static enum eos predefined_encoding(void) | |||||||
| } | } | ||||||
| // set current encoding ("!convtab" pseudo opcode) | // set current encoding ("!convtab" pseudo opcode) | ||||||
| // (allows for block, so must be reentrant) | // (allows for block, so must be reentrant) | ||||||
|  | // FIXME: current code does not allow for stuff like | ||||||
|  | //	!convtab some_string_symbol + ".bin" | ||||||
|  | // because anything not starting with '<' or '"' is supposed to be a keyword. | ||||||
|  | // maybe fix this by using | ||||||
|  | //	!convtab file = base + ".txt" | ||||||
|  | // in the future? | ||||||
|  | // another workaround would be: | ||||||
|  | //	!convtab "" + some_string_symbol + ".bin" | ||||||
|  | // but even then input_read_input_filename needs to be fixed! | ||||||
| static enum eos po_convtab(void) | static enum eos po_convtab(void) | ||||||
| { | { | ||||||
| 	boolean	uses_lib; | 	boolean	uses_lib; | ||||||
| @@ -367,7 +376,7 @@ static enum eos po_convtab(void) | |||||||
|  |  | ||||||
| 	if ((GotByte == '<') || (GotByte == '"')) { | 	if ((GotByte == '<') || (GotByte == '"')) { | ||||||
| 		// encoding table from file | 		// encoding table from file | ||||||
| 		if (input_read_filename(TRUE, &uses_lib)) | 		if (input_read_input_filename(&uses_lib)) | ||||||
| 			return SKIP_REMAINDER;	// missing or unterminated file name | 			return SKIP_REMAINDER;	// missing or unterminated file name | ||||||
|  |  | ||||||
| 		stream = includepaths_open_ro(uses_lib); | 		stream = includepaths_open_ro(uses_lib); | ||||||
| @@ -403,6 +412,8 @@ static enum eos encode_string(const struct encoder *inner_encoder, unsigned char | |||||||
| 			// eat closing quote | 			// eat closing quote | ||||||
| 			GetByte(); | 			GetByte(); | ||||||
| 			// now convert to unescaped version | 			// now convert to unescaped version | ||||||
|  | 			// FIXME - next call does nothing because wanted<escaping! | ||||||
|  | 			// FIXME - there is another block like this in line 1317! | ||||||
| 			if (input_unescape_dynabuf(0)) | 			if (input_unescape_dynabuf(0)) | ||||||
| 				return SKIP_REMAINDER;	// escaping error | 				return SKIP_REMAINDER;	// escaping error | ||||||
|  |  | ||||||
| @@ -467,7 +478,7 @@ static enum eos po_binary(void) | |||||||
| 	skip.val.intval	= 0; | 	skip.val.intval	= 0; | ||||||
|  |  | ||||||
| 	// if file name is missing, don't bother continuing | 	// if file name is missing, don't bother continuing | ||||||
| 	if (input_read_filename(TRUE, &uses_lib)) | 	if (input_read_input_filename(&uses_lib)) | ||||||
| 		return SKIP_REMAINDER; | 		return SKIP_REMAINDER; | ||||||
|  |  | ||||||
| 	// try to open file | 	// try to open file | ||||||
| @@ -767,7 +778,7 @@ static enum eos po_symbollist(void) | |||||||
|  |  | ||||||
| 	// read filename to global dynamic buffer | 	// read filename to global dynamic buffer | ||||||
| 	// if no file name given, exit (complaining will have been done) | 	// if no file name given, exit (complaining will have been done) | ||||||
| 	if (input_read_filename(FALSE, NULL)) | 	if (input_read_output_filename()) | ||||||
| 		return SKIP_REMAINDER; | 		return SKIP_REMAINDER; | ||||||
|  |  | ||||||
| 	// only process this pseudo opcode in first pass | 	// only process this pseudo opcode in first pass | ||||||
| @@ -849,7 +860,7 @@ static enum eos po_source(void)	// now GotByte = illegal char | |||||||
| 	if (--source_recursions_left < 0) | 	if (--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. quit function on error | ||||||
| 	if (input_read_filename(TRUE, &uses_lib)) | 	if (input_read_input_filename(&uses_lib)) | ||||||
| 		return SKIP_REMAINDER; | 		return SKIP_REMAINDER; | ||||||
|  |  | ||||||
| 	// if file could be opened, parse it. otherwise, complain | 	// if file could be opened, parse it. otherwise, complain | ||||||
| @@ -1302,6 +1313,8 @@ static enum eos throw_src_string(enum debuglevel level, const char prefix[]) | |||||||
| 			// eat closing quote | 			// eat closing quote | ||||||
| 			GetByte(); | 			GetByte(); | ||||||
| 			// now convert to unescaped version | 			// now convert to unescaped version | ||||||
|  | 			// FIXME - next call does nothing because wanted<escaping! | ||||||
|  | 			// FIXME - there is another block like this in line 416! | ||||||
| 			if (input_unescape_dynabuf(0)) | 			if (input_unescape_dynabuf(0)) | ||||||
| 				return SKIP_REMAINDER;	// escaping error | 				return SKIP_REMAINDER;	// escaping error | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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	"10 Feb"	// update before release	FIXME | #define CHANGE_DATE	"11 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 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user