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:
		| @@ -45,7 +45,7 @@ do {				\ | ||||
|  | ||||
| // output of platform-specific command line switches | ||||
| #define PLATFORM_OPTION_HELP	\ | ||||
| "  -t, --throwback        use the DDEUtils module's \"throwback\" protocol\n" | ||||
| "  -t, --throwback           use the DDEUtils module's \"throwback\" protocol\n" | ||||
|  | ||||
| // processing of platform-specific command line switches | ||||
| #define PLATFORM_SHORTOPTION_CODE			\ | ||||
|   | ||||
							
								
								
									
										127
									
								
								src/acme.c
									
									
									
									
									
								
							
							
						
						
									
										127
									
								
								src/acme.c
									
									
									
									
									
								
							| @@ -54,6 +54,7 @@ static const char	arg_vicelabels[]	= "VICE labels filename"; | ||||
| #define OPTION_VICELABELS	"vicelabels" | ||||
| #define OPTION_REPORT		"report" | ||||
| #define OPTION_SETPC		"setpc" | ||||
| #define OPTION_FROM_TO		"from-to" | ||||
| #define OPTION_CPU		"cpu" | ||||
| #define OPTION_INITMEM		"initmem" | ||||
| #define OPTION_MAXERRORS	"maxerrors" | ||||
| @@ -79,9 +80,6 @@ static const char	arg_vicelabels[]	= "VICE labels filename"; | ||||
| // variables | ||||
| static const char	**toplevel_sources; | ||||
| 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; | ||||
| const char		*symbollist_filename	= NULL; | ||||
| const char		*vicelabels_filename	= NULL; | ||||
| @@ -124,40 +122,41 @@ static void show_help_and_exit(void) | ||||
| "acme [OPTION...] [FILE]...\n" | ||||
| "\n" | ||||
| "Options:\n" | ||||
| "  -h, --" OPTION_HELP "             show this help and exit\n" | ||||
| "  -f, --" OPTION_FORMAT " FORMAT    set output file format\n" | ||||
| "  -o, --" OPTION_OUTFILE " FILE     set output file name\n" | ||||
| "  -r, --" OPTION_REPORT " FILE      set report file name\n" | ||||
| "  -l, --" OPTION_SYMBOLLIST " FILE  set symbol list file name\n" | ||||
| "      --" OPTION_LABELDUMP "        (old name for --" OPTION_SYMBOLLIST ")\n" | ||||
| "      --" OPTION_VICELABELS " FILE  set file name for label dump in VICE format\n" | ||||
| "      --" OPTION_SETPC " VALUE      set program counter\n" | ||||
| "      --" OPTION_CPU " CPU          set target processor\n" | ||||
| "      --" OPTION_INITMEM " VALUE    define 'empty' memory\n" | ||||
| "      --" OPTION_MAXERRORS " NUMBER set number of errors before exiting\n" | ||||
| "      --" OPTION_MAXDEPTH " NUMBER  set recursion depth for macro calls and !src\n" | ||||
| "      --" OPTION_IGNORE_ZEROES "    do not determine number size by leading zeroes\n" | ||||
| "      --" OPTION_STRICT_SEGMENTS "  turn segment overlap warnings into errors\n" | ||||
| "      --" OPTION_STRICT "           treat all warnings like errors\n" | ||||
| "  -vDIGIT                set verbosity level\n" | ||||
| "  -DSYMBOL=VALUE         define global symbol\n" | ||||
| "  -I PATH/TO/DIR         add search path for input files\n" | ||||
| "  -h, --" OPTION_HELP "                show this help and exit\n" | ||||
| "  -f, --" OPTION_FORMAT " FORMAT       set output file format\n" | ||||
| "  -o, --" OPTION_OUTFILE " FILE        set output file name\n" | ||||
| "  -r, --" OPTION_REPORT " FILE         set report file name\n" | ||||
| "  -l, --" OPTION_SYMBOLLIST " FILE     set symbol list file name\n" | ||||
| "      --" OPTION_LABELDUMP "           (old name for --" OPTION_SYMBOLLIST ")\n" | ||||
| "      --" OPTION_VICELABELS " FILE     set file name for label dump in VICE format\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_INITMEM " VALUE       define 'empty' memory\n" | ||||
| "      --" OPTION_MAXERRORS " NUMBER    set number of errors before exiting\n" | ||||
| "      --" OPTION_MAXDEPTH " NUMBER     set recursion depth for macro calls and !src\n" | ||||
| "      --" OPTION_IGNORE_ZEROES "       do not determine number size by leading zeroes\n" | ||||
| "      --" OPTION_STRICT_SEGMENTS "     turn segment overlap warnings into errors\n" | ||||
| "      --" OPTION_STRICT "              treat all warnings like errors\n" | ||||
| "  -vDIGIT                   set verbosity level\n" | ||||
| "  -DSYMBOL=VALUE            define global symbol\n" | ||||
| "  -I PATH/TO/DIR            add search path for input files\n" | ||||
| // TODO: replace these: | ||||
| "  -W" OPTIONWNO_LABEL_INDENT "      suppress warnings about indented labels\n" | ||||
| "  -W" OPTIONWNO_OLD_FOR "           (old, use \"--dialect 0.94.8\" instead)\n" | ||||
| "  -W" OPTIONWNO_BIN_LEN "           suppress warnings about lengths of binary literals\n" | ||||
| "  -W" OPTIONWTYPE_MISMATCH "        enable type checking (warn about type mismatch)\n" | ||||
| "  -W" OPTIONWNO_LABEL_INDENT "         suppress warnings about indented labels\n" | ||||
| "  -W" OPTIONWNO_OLD_FOR "              (old, use \"--dialect 0.94.8\" instead)\n" | ||||
| "  -W" OPTIONWNO_BIN_LEN "              suppress warnings about lengths of binary literals\n" | ||||
| "  -W" OPTIONWTYPE_MISMATCH "           enable type checking (warn about type mismatch)\n" | ||||
| // with this line and add a separate function: | ||||
| //"  -W                     show warning level options\n" | ||||
| "      --" OPTION_USE_STDOUT "       fix for 'Relaunch64' IDE (see docs)\n" | ||||
| "      --" OPTION_MSVC "             output errors in MS VS format\n" | ||||
| "      --" OPTION_COLOR "            use ANSI color codes for error output\n" | ||||
| "      --" OPTION_FULLSTOP "         use '.' as pseudo opcode prefix\n" | ||||
| "      --" OPTION_DIALECT " VERSION  behave like different version\n" | ||||
| "      --" OPTION_DEBUGLEVEL " VALUE drop all higher-level debug messages\n" | ||||
| "      --" OPTION_TEST "             enable experimental features\n" | ||||
| "      --" OPTION_USE_STDOUT "          fix for 'Relaunch64' IDE (see docs)\n" | ||||
| "      --" OPTION_MSVC "                output errors in MS VS format\n" | ||||
| "      --" OPTION_COLOR "               use ANSI color codes for error output\n" | ||||
| "      --" OPTION_FULLSTOP "            use '.' as pseudo opcode prefix\n" | ||||
| "      --" OPTION_DIALECT " VERSION     behave like different version\n" | ||||
| "      --" OPTION_DEBUGLEVEL " VALUE    drop all higher-level debug messages\n" | ||||
| "      --" OPTION_TEST "                enable experimental features\n" | ||||
| PLATFORM_OPTION_HELP | ||||
| "  -V, --" OPTION_VERSION "          show version and exit\n"); | ||||
| "  -V, --" OPTION_VERSION "             show version and exit\n"); | ||||
| 	exit(EXIT_SUCCESS); | ||||
| } | ||||
|  | ||||
| @@ -256,8 +255,8 @@ static void perform_pass(void) | ||||
| 	output_passinit();	// disable output, PC undefined | ||||
| 	cputype_passinit(default_cpu);	// set default cpu type | ||||
| 	// if start address was given on command line, use it: | ||||
| 	if (start_address != ILLEGAL_START_ADDRESS) | ||||
| 		vcpu_set_pc(start_address, 0); | ||||
| 	if (config.initial_pc != NO_VALUE_GIVEN) | ||||
| 		vcpu_set_pc(config.initial_pc, 0);	// 0 -> no segment flags | ||||
| 	encoding_passinit();	// set default encoding | ||||
| 	section_passinit();	// set initial zone (untitled) | ||||
| 	// init variables | ||||
| @@ -419,29 +418,27 @@ static signed long string_to_number(const char *string) | ||||
| 		could_not_parse(end); | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
|  | ||||
| // set program counter | ||||
| static void set_starting_pc(const char expression[]) | ||||
| // wrapper for fn above: complain about negative numbers | ||||
| static signed long string_to_nonneg_number(const char *string) | ||||
| { | ||||
| 	start_address = string_to_number(expression); | ||||
| 	if ((start_address > -1) && (start_address < 65536)) | ||||
| 		return; | ||||
| 	signed long	result	= string_to_number(string); | ||||
|  | ||||
| 	fprintf(stderr, "%sProgram counter out of range (0-0xffff).\n", cliargs_error); | ||||
| 	exit(EXIT_FAILURE); | ||||
| 	if (result < 0) { | ||||
| 		fprintf(stderr, "%sInvalid value, number is negative: '%s'.\n", cliargs_error, string); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
|  | ||||
| // set initial memory contents | ||||
| static void set_mem_contents(const char expression[]) | ||||
| { | ||||
| 	fill_value = string_to_number(expression); | ||||
| 	if ((fill_value >= -128) && (fill_value <= 255)) | ||||
| 		return; | ||||
|  | ||||
| 	fprintf(stderr, "%sInitmem value out of range (0-0xff).\n", cliargs_error); | ||||
| 	exit(EXIT_FAILURE); | ||||
| 	config.mem_init_value = string_to_number(expression); | ||||
| 	if ((config.mem_init_value < -128) || (config.mem_init_value > 255)) { | ||||
| 		fprintf(stderr, "%sInitmem value out of range (0-0xff).\n", cliargs_error); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -533,8 +530,11 @@ static const char *long_option(const char *string) | ||||
| 	else if (strcmp(string, OPTION_REPORT) == 0) | ||||
| 		report_filename = cliargs_safe_get_next(arg_reportfile); | ||||
| 	else if (strcmp(string, OPTION_SETPC) == 0) | ||||
| 		set_starting_pc(cliargs_safe_get_next("program counter")); | ||||
| 	else if (strcmp(string, OPTION_CPU) == 0) | ||||
| 		config.initial_pc = string_to_nonneg_number(cliargs_safe_get_next("program counter")); | ||||
| 	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) | ||||
| 	else if (strcmp(string, OPTION_INITMEM) == 0) | ||||
| 		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) { | ||||
| 		config.wanted_version = VER_FUTURE; | ||||
| 		config.test_new_features = TRUE; | ||||
| 		config.outbuf_size = 0x1000000;	// 16 MiB (FIXME - give it its own cli switch!) | ||||
| 	} PLATFORM_LONGOPTION_CODE | ||||
| 	else if (strcmp(string, OPTION_COLOR) == 0) | ||||
| 		config.format_color = TRUE; | ||||
| @@ -656,8 +657,28 @@ int main(int argc, const char *argv[]) | ||||
| 	cliargs_handle_options(short_option, long_option); | ||||
| 	// generate list of files to process | ||||
| 	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 | ||||
| 	output_createbuffer(fill_value, /* use_large_buf= */ config.test_new_features); | ||||
| 	output_createbuffer(); | ||||
| 	if (do_actual_work()) | ||||
| 		save_output_file(); | ||||
| 	return ACME_finalize(EXIT_SUCCESS);	// dump labels, if wanted | ||||
|   | ||||
| @@ -72,8 +72,6 @@ struct listitem { | ||||
| // maximum nesting depth of "!src" and macro calls | ||||
| // is not actually a limitation, but a means of finding recursions | ||||
| #define MAX_NESTING	64 | ||||
| // default value for output buffer | ||||
| #define FILLVALUE_INITIAL	0 | ||||
| // default value for "!fill" | ||||
| #define FILLVALUE_FILL		0 | ||||
|  | ||||
|   | ||||
							
								
								
									
										50
									
								
								src/global.c
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								src/global.c
									
									
									
									
									
								
							| @@ -122,6 +122,11 @@ void config_default(struct config *conf) | ||||
| 	conf->test_new_features		= FALSE;	// enabled by --test | ||||
| 	conf->wanted_version		= VER_CURRENT;	// changed by --dialect | ||||
| 	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 | ||||
| @@ -164,8 +169,8 @@ boolean parser_change_nowarn_block_flag(boolean new_value) | ||||
| 	return old_value; | ||||
| } | ||||
|  | ||||
| #define SF_FOUND_BLANK		(1u << 0)	// statement had space or tab | ||||
| #define SF_IMPLIED_LABEL	(1u << 1)	// statement had implied label def | ||||
| #define SF_FOUND_BLANK		(1u << 0)	// statement started with space or tab | ||||
| #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_NOWARN_PREFIX	(1u << 3)	// suppress warnings for this statement | ||||
| static bits	statement_flags; | ||||
| @@ -181,15 +186,15 @@ extern void parser_set_nowarn_prefix(void) | ||||
| 	statement_flags |= SF_NOWARN_PREFIX; | ||||
| } | ||||
|  | ||||
| // Check and return whether first label of statement. Complain if not. | ||||
| static int first_label_of_statement(void) | ||||
| // Check and return whether first symbol of statement. Complain if not. | ||||
| static int first_symbol_of_statement(void) | ||||
| { | ||||
| 	if (statement_flags & SF_IMPLIED_LABEL) { | ||||
| 	if (statement_flags & SF_FOUND_SYMBOL) { | ||||
| 		Throw_error(exception_syntax); | ||||
| 		input_skip_remainder(); | ||||
| 		return FALSE; | ||||
| 	} | ||||
| 	statement_flags |= SF_IMPLIED_LABEL;	// now there has been one | ||||
| 	statement_flags |= SF_FOUND_SYMBOL;	// now there has been one | ||||
| 	return TRUE; | ||||
| } | ||||
|  | ||||
| @@ -270,20 +275,21 @@ static void parse_symbol_definition(scope_t scope) | ||||
| // Parse global symbol definition or assembler mnemonic | ||||
| 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 | ||||
|  | ||||
| 	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 | ||||
| 		// 04 Jun 2005: this fix should help to explain "strange" error messages. | ||||
| 		// 17 May 2014: now it works for UTF-8 as well. | ||||
| 		if ((*GLOBALDYNABUF_CURRENT == (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."); | ||||
| 		parse_symbol_definition(SCOPE_GLOBAL); | ||||
| 	} | ||||
| 	// 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 | ||||
|  | ||||
| 	// Now GotByte = illegal char | ||||
| 	// 04 Jun 2005: this fix should help to explain "strange" error messages. | ||||
| 	// 17 May 2014: now it works for UTF-8 as well. | ||||
| 	if ((*GLOBALDYNABUF_CURRENT == (char) 0xa0) | ||||
| 	|| ((GlobalDynaBuf->size >= 2) && (GLOBALDYNABUF_CURRENT[0] == (char) 0xc2) && (GLOBALDYNABUF_CURRENT[1] == (char) 0xa0))) | ||||
| 		Throw_first_pass_warning("Symbol name starts with a shift-space character."); | ||||
| 	parse_symbol_definition(SCOPE_GLOBAL); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -292,7 +298,7 @@ static void parse_local_symbol_def(void) | ||||
| { | ||||
| 	scope_t	scope; | ||||
|  | ||||
| 	if (!first_label_of_statement()) | ||||
| 	if (!first_symbol_of_statement()) | ||||
| 		return; | ||||
|  | ||||
| 	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 == '-' | ||||
| static void parse_backward_anon_def(void) | ||||
| { | ||||
| 	if (!first_label_of_statement()) | ||||
| 	if (!first_symbol_of_statement()) | ||||
| 		return; | ||||
|  | ||||
| 	dynabuf_clear(GlobalDynaBuf); | ||||
| @@ -319,7 +325,7 @@ static void parse_backward_anon_def(void) | ||||
| // parse anonymous forward label definition. called with GotByte == ? | ||||
| static void parse_forward_anon_def(void) | ||||
| { | ||||
| 	if (!first_label_of_statement()) | ||||
| 	if (!first_symbol_of_statement()) | ||||
| 		return; | ||||
|  | ||||
| 	dynabuf_clear(GlobalDynaBuf); | ||||
|   | ||||
							
								
								
									
										11
									
								
								src/global.h
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								src/global.h
									
									
									
									
									
								
							| @@ -14,8 +14,8 @@ | ||||
| #include <string.h> | ||||
| #include "config.h" | ||||
|  | ||||
| #define LOCAL_PREFIX		'.'	// FIXME - this is not yet used consistently! | ||||
| #define CHEAP_PREFIX		'@'	// prefix character for cheap locals | ||||
| #define LOCAL_PREFIX	'.'	// FIXME - this is not yet used consistently! | ||||
| #define CHEAP_PREFIX	'@'	// prefix character for cheap locals | ||||
|  | ||||
| // Constants | ||||
|  | ||||
| @@ -77,6 +77,13 @@ struct config { | ||||
| 	boolean		test_new_features;	// FALSE, enabled by --test | ||||
| 	enum version	wanted_version;	// set by --dialect (and --test --test) | ||||
| 	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; | ||||
|  | ||||
|   | ||||
							
								
								
									
										160
									
								
								src/input.c
									
									
									
									
									
								
							
							
						
						
									
										160
									
								
								src/input.c
									
									
									
									
									
								
							| @@ -339,11 +339,25 @@ static char GetQuotedByte(void) | ||||
| } | ||||
|  | ||||
| // 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) | ||||
| { | ||||
| 	while (GotByte) | ||||
| 	while (GotByte) { | ||||
| 		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 | ||||
| @@ -599,33 +613,51 @@ int input_read_and_lower_keyword(void) | ||||
| 	return length; | ||||
| } | ||||
|  | ||||
| // Try to read a file name. | ||||
| // If "allow_library" is TRUE, library access by using <...> quoting | ||||
| // is possible as well. If "uses_lib" is non-NULL, info about library | ||||
| // usage is stored there. | ||||
| // shared ending when trying to read a file name. | ||||
| // 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_filename(boolean allow_library, boolean *uses_lib) | ||||
| static int read_filename_shared_end(int prefix_size) | ||||
| { | ||||
| 	int	start_of_string; | ||||
| 	char	*lib_prefix, | ||||
| 		terminator; | ||||
| 	// check length | ||||
| 	if (GlobalDynaBuf->size == prefix_size) { | ||||
| 		Throw_error("No file name given."); | ||||
| 		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(); | ||||
| 	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 | ||||
| 		} | ||||
|  | ||||
| 	if (GotByte == '<') { | ||||
| 		// library access: | ||||
| 		*uses_lib = TRUE; | ||||
| 		// read platform's lib prefix | ||||
| 		lib_prefix = PLATFORM_LIBPREFIX; | ||||
| #ifndef NO_NEED_FOR_ENV_VAR | ||||
| @@ -635,45 +667,71 @@ int input_read_filename(boolean allow_library, boolean *uses_lib) | ||||
| 			return 1;	// error | ||||
| 		} | ||||
| #endif | ||||
| 		// copy lib path and set quoting char | ||||
| 		// copy lib path | ||||
| 		dynabuf_add_string(GlobalDynaBuf, lib_prefix); | ||||
| 		terminator = '>'; | ||||
| 		break; | ||||
| 	case '"':	// normal access | ||||
| 		if (uses_lib) | ||||
| 			*uses_lib = FALSE; | ||||
| 		terminator = '"'; | ||||
| 		break; | ||||
| 	default:	// none of the above | ||||
| 		Throw_error("File name quotes not found (\"\" or <>)."); | ||||
| 		// 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 | ||||
|  | ||||
| 		GetByte();	// eat '>' terminator | ||||
| 	} 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 <>)."); | ||||
| 			return 1;	// error | ||||
| 		} | ||||
| 		// read file name string | ||||
| 		if (input_quoted_to_dynabuf('"')) | ||||
| 			return 1;	// unterminated or escaping error | ||||
|  | ||||
| 		GetByte();	// eat terminator | ||||
| // new algo: | ||||
| // it should be possible to construct the name of input file from symbols, so | ||||
| // 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 | ||||
| 	} | ||||
| 	// remember border between optional library prefix and string from assembler source file | ||||
| 	start_of_string = GlobalDynaBuf->size; | ||||
| 	// read file name string | ||||
| 	if (input_quoted_to_dynabuf(terminator)) | ||||
| 	if (GotByte != '"') { | ||||
| 		Throw_error("File name quotes not found (\"\")."); | ||||
| 		return 1;	// error | ||||
| 	} | ||||
| 	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 | ||||
| 	if (GlobalDynaBuf->size == start_of_string) { | ||||
| 		Throw_error("No file name given."); | ||||
| 		return 1;	// error | ||||
| 	} | ||||
|  | ||||
| 	// resolve backslash escapes | ||||
| 	if (input_unescape_dynabuf(start_of_string)) | ||||
| 		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 | ||||
| 	// 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 | ||||
| // found, otherwise FALSE. | ||||
| int input_accept_comma(void) | ||||
|   | ||||
							
								
								
									
										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. | ||||
| extern int input_read_and_lower_keyword(void); | ||||
|  | ||||
| // Try to read a file name. | ||||
| // If "allow_library" is TRUE, library access by using <...> quoting | ||||
| // is possible as well. If "uses_lib" is non-NULL, info about library | ||||
| // usage is stored there. | ||||
| // 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. | ||||
| 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 | ||||
| // found, otherwise FALSE. | ||||
|   | ||||
							
								
								
									
										57
									
								
								src/output.c
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								src/output.c
									
									
									
									
									
								
							| @@ -38,8 +38,7 @@ struct segment { | ||||
| // structure for all output stuff: | ||||
| struct output { | ||||
| 	// output buffer stuff | ||||
| 	intval_t	bufsize;	// either 64 KiB or 16 MiB | ||||
| 	char		*buffer;	// holds assembled code | ||||
| 	char		*buffer;	// holds assembled code (size is config.outbuf_size) | ||||
| 	intval_t	write_idx;	// index of next write | ||||
| 	intval_t	lowest_written;		// smallest 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) | ||||
| 		test_segment = test_segment->next; | ||||
| 	if (test_segment == &out->segment.list_head) | ||||
| 		out->segment.max = out->bufsize - 1; | ||||
| 		out->segment.max = config.outbuf_size - 1; | ||||
| 	else | ||||
| 		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) | ||||
| { | ||||
| 	if (current_offset >= out->bufsize) | ||||
| 	if (current_offset >= config.outbuf_size) | ||||
| 		Throw_serious_error("Produced too much code."); | ||||
| 	// TODO - get rid of FIRST_PASS condition, because user can suppress these warnings if they want | ||||
| 	if (FIRST_PASS) { | ||||
| @@ -206,7 +205,7 @@ void output_skip(int size) | ||||
| // fill output buffer with given byte 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) | ||||
| void output_createbuffer(signed long fill_value, boolean use_large_buf) | ||||
| void output_createbuffer(void) | ||||
| { | ||||
| 	out->bufsize = use_large_buf ? 0x1000000 : 0x10000; | ||||
| 	out->buffer = safe_malloc(out->bufsize); | ||||
| 	if (fill_value == MEMINIT_USE_DEFAULT) { | ||||
| 		fill_value = FILLVALUE_INITIAL; | ||||
| 		out->initvalue_set = FALSE; | ||||
| 	char	fill_value	= 0;	// default value for output buffer | ||||
|  | ||||
| 	out->buffer = safe_malloc(config.outbuf_size); | ||||
| 	if (config.mem_init_value == MEMINIT_USE_DEFAULT) { | ||||
| 		out->initvalue_set = FALSE;	// "!initmem" can be used | ||||
| 	} 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) | ||||
| 	fill_completely(fill_value & 0xff); | ||||
| 	fill_completely(fill_value); | ||||
| 	// init ring list of segments | ||||
| 	out->segment.list_head.next = &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) | ||||
| { | ||||
| 	intval_t	start, | ||||
| 			end, | ||||
| 			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 | ||||
| 		start = 0;	// I could try to use some segment start, but what for? | ||||
| 		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 { | ||||
| 		start = out->lowest_written; | ||||
| 		amount = out->highest_written - start + 1; | ||||
| 		amount = end - start + 1; | ||||
| 	} | ||||
| 	if (config.process_verbosity) | ||||
| 		printf("Saving %ld (0x%lx) bytes (0x%lx - 0x%lx exclusive).\n", | ||||
| 			amount, amount, start, start + amount); | ||||
| 	// output file header according to file format | ||||
| 	// FIXME - add checks and error messages for "start is above $ffff"!) | ||||
| 	switch (output_format) { | ||||
| 	case OUTPUT_FORMAT_APPLE: | ||||
| 		PLATFORM_SETFILETYPE_APPLE(output_filename); | ||||
| @@ -402,13 +413,13 @@ void output_passinit(void) | ||||
| //	} | ||||
|  | ||||
| 	// 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; | ||||
| 	// deactivate output - any byte written will trigger error: | ||||
| 	output_byte = no_output; | ||||
| 	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.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->xor = 0; | ||||
|  | ||||
| @@ -467,7 +478,7 @@ void output_start_segment(intval_t address_change, bits segment_flags) | ||||
| 	output_end_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.flags = segment_flags; | ||||
| 	// allow writing to output buffer | ||||
| @@ -568,7 +579,7 @@ int vcpu_get_statement_size(void) | ||||
| // adjust program counter (called at end of each statement) | ||||
| 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; | ||||
| } | ||||
|  | ||||
| @@ -607,7 +618,7 @@ void pseudopc_end(void) | ||||
| 		if (config.wanted_version >= VER_DISABLED_OBSOLETE_STUFF) | ||||
| 			BUG("ClosingUnopenedPseudopcBlock", 0); | ||||
| 	} 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; | ||||
| 		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 | ||||
| 		} | ||||
| 		// 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; | ||||
| 	} | ||||
| 	return 0;	// ok | ||||
|   | ||||
| @@ -12,7 +12,7 @@ | ||||
|  | ||||
|  | ||||
| // constants | ||||
| #define MEMINIT_USE_DEFAULT	256 | ||||
|  | ||||
| // segment flags | ||||
| #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 | ||||
| @@ -43,7 +43,7 @@ extern void output_passinit(void); | ||||
| // outbuf stuff: | ||||
|  | ||||
| // 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 | ||||
| // (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. | ||||
| 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); | ||||
|  | ||||
| // change output pointer and enable output | ||||
|   | ||||
| @@ -136,7 +136,7 @@ static enum eos po_to(void) | ||||
|  | ||||
| 	// read filename to global dynamic buffer | ||||
| 	// if no file name given, exit (complaining will have been done) | ||||
| 	if (input_read_filename(FALSE, NULL)) | ||||
| 	if (input_read_output_filename()) | ||||
| 		return SKIP_REMAINDER; | ||||
|  | ||||
| 	// 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) | ||||
| // (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) | ||||
| { | ||||
| 	boolean	uses_lib; | ||||
| @@ -367,7 +376,7 @@ static enum eos po_convtab(void) | ||||
|  | ||||
| 	if ((GotByte == '<') || (GotByte == '"')) { | ||||
| 		// 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 | ||||
|  | ||||
| 		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 | ||||
| 			GetByte(); | ||||
| 			// 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)) | ||||
| 				return SKIP_REMAINDER;	// escaping error | ||||
|  | ||||
| @@ -467,7 +478,7 @@ static enum eos po_binary(void) | ||||
| 	skip.val.intval	= 0; | ||||
|  | ||||
| 	// 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; | ||||
|  | ||||
| 	// try to open file | ||||
| @@ -767,7 +778,7 @@ static enum eos po_symbollist(void) | ||||
|  | ||||
| 	// read filename to global dynamic buffer | ||||
| 	// if no file name given, exit (complaining will have been done) | ||||
| 	if (input_read_filename(FALSE, NULL)) | ||||
| 	if (input_read_output_filename()) | ||||
| 		return SKIP_REMAINDER; | ||||
|  | ||||
| 	// 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) | ||||
| 		Throw_serious_error("Too deeply nested. Recursive \"!source\"?"); | ||||
| 	// read file name. quit function on error | ||||
| 	if (input_read_filename(TRUE, &uses_lib)) | ||||
| 	if (input_read_input_filename(&uses_lib)) | ||||
| 		return SKIP_REMAINDER; | ||||
|  | ||||
| 	// 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 | ||||
| 			GetByte(); | ||||
| 			// 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)) | ||||
| 				return SKIP_REMAINDER;	// escaping error | ||||
|  | ||||
|   | ||||
| @@ -9,7 +9,7 @@ | ||||
|  | ||||
| #define RELEASE		"0.97"		// update before release	FIXME | ||||
| #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 HOME_PAGE	"http://home.pages.de/~mac_bacon/smorbrod/acme/" | ||||
| #define HOME_PAGE	"http://sourceforge.net/p/acme-crossass/"	// FIXME | ||||
|   | ||||
		Reference in New Issue
	
	Block a user