diff --git a/src/_amiga.h b/src/_amiga.h index 0dfa004..d6fbe82 100644 --- a/src/_amiga.h +++ b/src/_amiga.h @@ -27,6 +27,7 @@ #define PLATFORM_SETFILETYPE_TEXT(a) // platform specific message output +#define PLATFORM_INFO(a) #define PLATFORM_WARNING(a) #define PLATFORM_ERROR(a) #define PLATFORM_SERIOUS(a) diff --git a/src/_dos.h b/src/_dos.h index d123407..22cac41 100644 --- a/src/_dos.h +++ b/src/_dos.h @@ -27,6 +27,7 @@ #define PLATFORM_SETFILETYPE_TEXT(a) // platform specific message output +#define PLATFORM_INFO(a) #define PLATFORM_WARNING(a) #define PLATFORM_ERROR(a) #define PLATFORM_SERIOUS(a) diff --git a/src/_riscos.h b/src/_riscos.h index 8795084..74fdcee 100644 --- a/src/_riscos.h +++ b/src/_riscos.h @@ -30,6 +30,7 @@ #define PLATFORM_SETFILETYPE_TEXT(a) RISCOS_set_filetype(a, 0xfff) // platform specific message output +#define PLATFORM_INFO(a) RISCOS_throwback(a, 0) #define PLATFORM_WARNING(a) RISCOS_throwback(a, 0) #define PLATFORM_ERROR(a) RISCOS_throwback(a, 1) #define PLATFORM_SERIOUS(a) RISCOS_throwback(a, 2) diff --git a/src/_std.h b/src/_std.h index 7c8efbd..c58f2d6 100644 --- a/src/_std.h +++ b/src/_std.h @@ -27,6 +27,7 @@ #define PLATFORM_SETFILETYPE_TEXT(a) // platform specific message output +#define PLATFORM_INFO(a) #define PLATFORM_WARNING(a) #define PLATFORM_ERROR(a) #define PLATFORM_SERIOUS(a) diff --git a/src/acme.c b/src/acme.c index abfa83a..46de09e 100644 --- a/src/acme.c +++ b/src/acme.c @@ -333,6 +333,7 @@ static void save_output_file(void) #define PF_COMPLAIN_ABOUT_UNDEFINEDS (1u << 0) // throw "Symbol not defined" errors #define PF_THROW_SEGMENT_MESSAGES (1u << 1) // throw segment warnings/errors #define PF_GENERATE_OUTPUT (1u << 2) // generate output and/or report file +#define PF_IS_FINAL_PASS (1u << 3) // mostly for special warnings // perform a single pass static void perform_pass(bits passflags) @@ -347,6 +348,7 @@ static void perform_pass(bits passflags) pass.counters.errors = 0; pass.counters.warnings = 0; pass.flags.complain_about_undefined = !!(passflags & PF_COMPLAIN_ABOUT_UNDEFINEDS); + pass.flags.is_final_pass = !!(passflags & PF_IS_FINAL_PASS); pass.flags.throw_segment_messages = !!(passflags & PF_THROW_SEGMENT_MESSAGES); pass.flags.generate_output = !!(passflags & PF_GENERATE_OUTPUT); @@ -439,19 +441,19 @@ static void do_actual_work(void) } } -// last pass: +// final pass: // any errors left? if (pass.counters.undefineds == 0) { // FIXME - use pass.counters.needvalue instead! // victory lap if (config.process_verbosity >= 2) puts("Extra pass to generate output."); - perform_pass(PF_GENERATE_OUTPUT); + perform_pass(PF_IS_FINAL_PASS | PF_GENERATE_OUTPUT); } else { // There are still errors (unsolvable by doing further passes), // so perform additional pass to find and show them. if (config.process_verbosity >= 2) puts("Extra pass to display errors."); - perform_pass(PF_COMPLAIN_ABOUT_UNDEFINEDS); // perform pass, but now show "value undefined" + perform_pass(PF_IS_FINAL_PASS | PF_COMPLAIN_ABOUT_UNDEFINEDS); // perform pass, but now show "value undefined" // FIXME - perform_pass() calls exit() when there were errors, // so if controls returns here, call BUG()! // (this can be triggered using ifdef/ifndef) diff --git a/src/alu.c b/src/alu.c index d26f027..820cac6 100644 --- a/src/alu.c +++ b/src/alu.c @@ -250,7 +250,7 @@ static void enlarge_operator_stack(void) //printf("Doubling op stack size to %d.\n", opstack_size); op_stack = realloc(op_stack, opstack_size * sizeof(*op_stack)); if (op_stack == NULL) - Throw_serious_error(exception_no_memory_left); + throw_serious_error(exception_no_memory_left); } @@ -261,7 +261,7 @@ static void enlarge_argument_stack(void) //printf("Doubling arg stack size to %d.\n", argstack_size); arg_stack = realloc(arg_stack, argstack_size * sizeof(*arg_stack)); if (arg_stack == NULL) - Throw_serious_error(exception_no_memory_left); + throw_serious_error(exception_no_memory_left); } @@ -332,7 +332,7 @@ static void is_not_defined(struct symbol *optional_symbol, char *name, size_t le } dynabuf_add_string(errormsg_dyna_buf, ")."); dynabuf_append(errormsg_dyna_buf, '\0'); - Throw_error(errormsg_dyna_buf->buffer); + throw_error(errormsg_dyna_buf->buffer); } @@ -367,7 +367,7 @@ static void get_symbol_value(scope_t scope, size_t name_length, unsigned int unp if (arg->type == &type_number) { pseudopc_unpseudo(&arg->u.number, symbol->pseudopc, unpseudo_count); } else { - Throw_error("Un-pseudopc operator '&' can only be applied to number symbols."); + throw_error("Un-pseudopc operator '&' can only be applied to number symbols."); } } // if needed, output "value not defined" error @@ -438,13 +438,13 @@ static void parse_quoted(char closing_quote) // single character //////////////////////// // too short? if (GlobalDynaBuf->size == 0) { - Throw_error(exception_missing_string); + throw_error(exception_missing_string); goto fail; } // too long? if (GlobalDynaBuf->size != 1) - Throw_error("There's more than one character."); + throw_error("There's more than one character."); // parse character value = encoding_encode_char(GLOBALDYNABUF_CURRENT[0]); PUSH_INT_ARG(value, 0, 0); // no flags, no addr refs @@ -482,11 +482,10 @@ static void parse_binary_literal(void) // Now GotByte = "%" or "b" break; // found illegal character } if (!digits) { - Throw_error("Binary literal without any digits."); + throw_error("Binary literal without any digits."); } if (digits & config.warn_bin_mask) { - if (pass.number == 1) - Throw_warning("Binary literal with strange number of digits."); + throw_finalpass_warning("Binary literal with strange number of digits."); } // set force bits if (config.honor_leading_zeroes) { @@ -534,7 +533,7 @@ static void parse_hex_literal(void) // Now GotByte = "$" or "x" break; // found illegal character } if (!digits) - Throw_error("Hex literal without any digits."); + throw_error("Hex literal without any digits."); // set force bits if (config.honor_leading_zeroes) { if (digits > 2) { @@ -657,7 +656,7 @@ static void parse_function_call(void) if (tree_easy_scan(function_tree, &node_body, function_dyna_buf)) { PUSH_OP((struct op *) node_body); } else { - Throw_error("Unknown function."); + throw_error("Unknown function."); alu_state = STATE_ERROR; } } @@ -732,7 +731,7 @@ static int parse_octal_or_unpseudo(void) // now GotByte = '&' // // anonymous symbol // "unpseudo"-ing anonymous symbols is not supported } else { - Throw_error(exception_missing_string); // FIXME - create some "expected octal value or symbol name" error instead! + throw_error(exception_missing_string); // FIXME - create some "expected octal value or symbol name" error instead! return 1; // error } return 0; // ok @@ -784,7 +783,7 @@ static void handle_special_operator(struct expression *expression, enum op_id pr alu_state = STATE_EXPECT_DYADIC_OP; } else { // unmatched bracket - Throw_error("Unterminated list."); + throw_error("Unterminated list."); alu_state = STATE_ERROR; // remove previous operator by overwriting with newest one... PREVIOUS_OPERATOR = NEWEST_OPERATOR; @@ -798,7 +797,7 @@ static void handle_special_operator(struct expression *expression, enum op_id pr alu_state = STATE_EXPECT_DYADIC_OP; } else { // unmatched bracket - Throw_error("Unterminated index spec."); + throw_error("Unterminated index spec."); alu_state = STATE_ERROR; // remove previous operator by overwriting with newest one... PREVIOUS_OPERATOR = NEWEST_OPERATOR; @@ -1053,7 +1052,7 @@ static boolean expect_argument_or_monadic_operator(struct expression *expression if (op_stack[op_sp - 1] == &ops_start_expression) { push_dyadic_and_check(expression, &ops_terminating_char); } else { - Throw_error(exception_syntax); + throw_error(exception_syntax); alu_state = STATE_ERROR; } return FALSE; // found delimiter @@ -1131,8 +1130,7 @@ static void expect_dyadic_operator(struct expression *expression) if (GetByte() == '=') { GetByte(); // eat second '=' character } else { - //if (pass.number == 1) - // Throw_warning("old-style \"=\" comparison detected, please use \"==\" instead."); ACTIVATE! + //throw_finalpass_warning("old-style \"=\" comparison detected, please use \"==\" instead."); ACTIVATE! } goto push_dyadic_op; @@ -1211,7 +1209,7 @@ static void expect_dyadic_operator(struct expression *expression) goto push_dyadic_op; } - Throw_error("Unknown operator."); + throw_error("Unknown operator."); alu_state = STATE_ERROR; //goto end; } else { @@ -1252,7 +1250,7 @@ static void unsupported_operation(const struct object *optional, const struct op dynabuf_add_string(errormsg_dyna_buf, arg->type->name); dynabuf_add_string(errormsg_dyna_buf, "\"."); dynabuf_append(errormsg_dyna_buf, '\0'); - Throw_error(errormsg_dyna_buf->buffer); + throw_error(errormsg_dyna_buf->buffer); } @@ -1430,7 +1428,7 @@ static void number_assign(struct object *self, const struct object *new_value, b // symbol is already defined, so compare new and old values // if values differ, complain and return if (number_differs(self, new_value)) { - Throw_error(exception_symbol_defined); + throw_error(exception_symbol_defined); return; } // values are the same, so only fiddle with flags @@ -1458,7 +1456,7 @@ static void number_assign(struct object *self, const struct object *new_value, b static void list_assign(struct object *self, const struct object *new_value, boolean accept_change) { if ((!accept_change) && list_differs(self, new_value)) { - Throw_error(exception_symbol_defined); + throw_error(exception_symbol_defined); return; } *self = *new_value; @@ -1469,7 +1467,7 @@ static void list_assign(struct object *self, const struct object *new_value, boo static void string_assign(struct object *self, const struct object *new_value, boolean accept_change) { if ((!accept_change) && string_differs(self, new_value)) { - Throw_error(exception_symbol_defined); + throw_error(exception_symbol_defined); return; } *self = *new_value; @@ -1581,7 +1579,7 @@ static void float_ranged_fn(double (*fn)(double), struct object *self) if ((self->u.number.val.fpval >= -1) && (self->u.number.val.fpval <= 1)) { self->u.number.val.fpval = fn(self->u.number.val.fpval); } else { - Throw_error("Argument out of range."); // TODO - add number output to error message + throw_error("Argument out of range."); // TODO - add number output to error message self->u.number.val.fpval = 0; } } @@ -1796,8 +1794,7 @@ static void undef_handle_dyadic_operator(struct object *self, const struct op *o goto shared; case OPID_EOR: - if (pass.number == 1) - Throw_warning("\"EOR\" is deprecated; use \"XOR\" instead."); + throw_finalpass_warning("\"EOR\" is deprecated; use \"XOR\" instead."); // FIXME - change to error, at least for newest dialect! /*FALLTHROUGH*/ case OPID_XOR: case OPID_AND: @@ -1858,8 +1855,7 @@ static void int_handle_dyadic_operator(struct object *self, const struct op *op, case OPID_EOR: case OPID_XOR: // convert other to int, warning user - if (pass.number == 1) - Throw_warning(exception_float_to_int); // FIXME - warning is never seen if arguments are undefined in first pass! + throw_finalpass_warning(exception_float_to_int); /*FALLTHROUGH*/ case OPID_MODULO: case OPID_SHIFTLEFT: @@ -1892,7 +1888,7 @@ static void int_handle_dyadic_operator(struct object *self, const struct op *op, if (other->u.number.val.intval >= 0) { self->u.number.val.intval = my_pow(self->u.number.val.intval, other->u.number.val.intval); } else { - Throw_error("Exponent is negative."); + throw_error("Exponent is negative."); self->u.number.val.intval = 0; } break; @@ -1911,7 +1907,7 @@ static void int_handle_dyadic_operator(struct object *self, const struct op *op, if (other->u.number.val.intval) { self->u.number.val.intval %= other->u.number.val.intval; } else { - Throw_error(exception_div_by_zero); + throw_error(exception_div_by_zero); self->u.number.val.intval = 0; } break; @@ -1965,8 +1961,7 @@ static void int_handle_dyadic_operator(struct object *self, const struct op *op, refs = self->u.number.addr_refs + other->u.number.addr_refs; // add address references break; case OPID_EOR: - if (pass.number == 1) - Throw_warning("\"EOR\" is deprecated; use \"XOR\" instead."); + throw_finalpass_warning("\"EOR\" is deprecated; use \"XOR\" instead."); // FIXME - change to error, at least for newest dialect! /*FALLTHROUGH*/ case OPID_XOR: self->u.number.val.intval ^= other->u.number.val.intval; @@ -2049,7 +2044,7 @@ static void float_handle_dyadic_operator(struct object *self, const struct op *o if (other->u.number.val.fpval) { self->u.number.val.fpval /= other->u.number.val.fpval; } else { - Throw_error(exception_div_by_zero); + throw_error(exception_div_by_zero); self->u.number.val.fpval = 0; } break; @@ -2057,7 +2052,7 @@ static void float_handle_dyadic_operator(struct object *self, const struct op *o if (other->u.number.val.fpval) { self->u.number.val.intval = self->u.number.val.fpval / other->u.number.val.fpval; // fp becomes int! } else { - Throw_error(exception_div_by_zero); + throw_error(exception_div_by_zero); self->u.number.val.intval = 0; } self->u.number.ntype = NUMTYPE_INT; // result is int @@ -2067,8 +2062,7 @@ static void float_handle_dyadic_operator(struct object *self, const struct op *o case OPID_OR: case OPID_EOR: case OPID_XOR: - if (pass.number == 1) - Throw_warning(exception_float_to_int); // FIXME - warning is never seen if arguments are undefined in first pass! + throw_finalpass_warning(exception_float_to_int); /*FALLTHROUGH*/ case OPID_MODULO: float_to_int(self); @@ -2163,7 +2157,7 @@ static int get_valid_index(int *target, int length, const struct object *self, c return 1; } if (other->u.number.ntype == NUMTYPE_UNDEFINED) { - Throw_error("Index is undefined."); + throw_error("Index is undefined."); return 1; } if (other->u.number.ntype == NUMTYPE_FLOAT) @@ -2176,7 +2170,7 @@ static int get_valid_index(int *target, int length, const struct object *self, c if (index < 0) index += length; if ((index < 0) || (index >= length)) { - Throw_error("Index out of range."); + throw_error("Index out of range."); return 1; } *target = index; @@ -2550,9 +2544,9 @@ void ALU_any_int(intval_t *target) // ACCEPT_UNDEFINED parse_expression(&expression); // FIXME - check return value and pass to caller! if (expression.open_parentheses) - Throw_error(exception_paren_open); + throw_error(exception_paren_open); if (expression.is_empty) - Throw_error(exception_no_value); + throw_error(exception_no_value); if (expression.result.type == &type_number) { if (expression.result.u.number.ntype == NUMTYPE_UNDEFINED) *target = 0; @@ -2566,7 +2560,7 @@ void ALU_any_int(intval_t *target) // ACCEPT_UNDEFINED // accept single-char strings, to be more // compatible with versions before 0.97: if (expression.result.u.string->length != 1) { - Throw_error(exception_lengthnot1); + throw_error(exception_lengthnot1); } else { // FIXME - throw a warning? } @@ -2574,7 +2568,7 @@ void ALU_any_int(intval_t *target) // ACCEPT_UNDEFINED *target = expression.result.u.number.val.intval; } else { *target = 0; - Throw_error(exception_not_number); + throw_error(exception_not_number); } } @@ -2604,12 +2598,12 @@ or throws errors even though the result is defined! */ if (expression.open_parentheses) - Throw_error(exception_paren_open); + throw_error(exception_paren_open); if (expression.is_empty) - Throw_serious_error(exception_no_value); + throw_serious_error(exception_no_value); if (expression.result.type == &type_number) { if (expression.result.u.number.ntype == NUMTYPE_UNDEFINED) { - Throw_serious_error("Value not defined."); + throw_serious_error("Value not defined."); expression.result.u.number.val.intval = 0; } else if (expression.result.u.number.ntype == NUMTYPE_INT) { // ok @@ -2622,13 +2616,13 @@ throws errors even though the result is defined! // accept single-char strings, to be more // compatible with versions before 0.97: if (expression.result.u.string->length != 1) { - Throw_error(exception_lengthnot1); + throw_error(exception_lengthnot1); } else { // FIXME - throw a warning? } string_to_byte(&(expression.result), 0); } else { - Throw_serious_error(exception_not_number); + throw_serious_error(exception_not_number); } *intresult = expression.result.u.number; } @@ -2655,20 +2649,20 @@ void ALU_addrmode_int(struct expression *expression, int paren) // ACCEPT_UNDEFI // accept single-char strings, to be more // compatible with versions before 0.97: if (expression->result.u.string->length != 1) { - Throw_error(exception_lengthnot1); + throw_error(exception_lengthnot1); } else { // FIXME - throw a warning? } string_to_byte(&(expression->result), 0); } else { - Throw_error(exception_not_number); + throw_error(exception_not_number); } if (expression->open_parentheses > paren) { expression->open_parentheses = 0; - Throw_error(exception_paren_open); + throw_error(exception_paren_open); } if (expression->is_empty) - Throw_error(exception_no_value); + throw_error(exception_no_value); } @@ -2685,9 +2679,9 @@ void ALU_any_result(struct object *result) // ACCEPT_UNDEFINED | ACCEPT_FLOAT parse_expression(&expression); // FIXME - check return value and pass to caller! *result = expression.result; if (expression.open_parentheses) - Throw_error(exception_paren_open); + throw_error(exception_paren_open); if (expression.is_empty) - Throw_error(exception_no_value); + throw_error(exception_no_value); } @@ -2695,7 +2689,7 @@ void ALU_any_result(struct object *result) // ACCEPT_UNDEFINED | ACCEPT_FLOAT maybe move if (expression.is_empty) - Throw_error(exception_no_value); + throw_error(exception_no_value); to end of parse_expression() diff --git a/src/cpu.c b/src/cpu.c index f4def23..c7748f5 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -130,7 +130,7 @@ const struct cpu_type *cputype_find(void) void vcpu_check_and_set_reg_length(boolean *var, boolean make_long) { if (((cpu_current_type->flags & CPUFLAG_SUPPORTSLONGREGS) == 0) && make_long) - Throw_error("Chosen CPU does not support long registers."); + throw_error("Chosen CPU does not support long registers."); else *var = make_long; } diff --git a/src/dynabuf.c b/src/dynabuf.c index bfd8fa2..fd47146 100644 --- a/src/dynabuf.c +++ b/src/dynabuf.c @@ -38,7 +38,7 @@ static void resize(struct dynabuf *db, size_t new_size) //printf("Growing dynabuf to size %d.\n", new_size); new_buf = realloc(db->buffer, new_size); if (new_buf == NULL) - Throw_serious_error(exception_no_memory_left); + throw_serious_error(exception_no_memory_left); db->reserved = new_size; db->buffer = new_buf; } diff --git a/src/flow.c b/src/flow.c index 1714bd6..41bdcd8 100644 --- a/src/flow.c +++ b/src/flow.c @@ -192,7 +192,7 @@ void flow_store_doloop_condition(struct condition *condition, char terminator) } else if (strcmp(GlobalDynaBuf->buffer, "until") == 0) { condition->invert = TRUE; } else { - Throw_error("Expected WHILE or UNTIL keyword, or an empty loop condition."); + throw_error("Expected WHILE or UNTIL keyword, or an empty loop condition."); return; } // write given condition into buffer @@ -230,7 +230,7 @@ static boolean check_condition(struct condition *condition) GetByte(); // proceed with next char ALU_defined_int(&intresult); if (GotByte) - Throw_serious_error("Unexpected char when evaluating loop condition."); // FIXME - include that char in the error message! + throw_serious_error("Unexpected char when evaluating loop condition."); // FIXME - include that char in the error message! return condition->invert ? !intresult.val.intval : !!intresult.val.intval; } diff --git a/src/global.c b/src/global.c index d5cb82b..f5ed13a 100644 --- a/src/global.c +++ b/src/global.c @@ -143,7 +143,7 @@ void *safe_malloc(size_t size) void *block = malloc(size); if (block == NULL) - Throw_serious_error(exception_no_memory_left); + throw_serious_error(exception_no_memory_left); return block; } @@ -197,7 +197,7 @@ extern void parser_set_nowarn_prefix(void) static int first_symbol_of_statement(void) { if (statement_flags & SF_FOUND_SYMBOL) { - Throw_error("Unknown mnemonic"); + throw_error("Unknown mnemonic"); parser_skip_remainder(); return FALSE; } @@ -216,8 +216,7 @@ static void set_label(scope_t scope, bits force_bit, bits powers) struct object result; if ((statement_flags & SF_FOUND_BLANK) && config.warn_on_indented_labels) { - if (pass.number == 1) - Throw_warning("Label name not in leftmost column."); + throw_finalpass_warning("Label name not in leftmost column."); } symbol = symbol_find(scope); result.type = &type_number; @@ -288,8 +287,7 @@ static void parse_mnemo_or_global_symbol_def(void) // 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))) { - if (pass.number == 1) - Throw_warning("Symbol name starts with a shift-space character."); + throw_finalpass_warning("Symbol name starts with a shift-space character."); } parse_symbol_definition(SCOPE_GLOBAL); } @@ -399,7 +397,7 @@ void parse_until_eob_or_eof(void) if (BYTE_STARTS_KEYWORD(GotByte)) { parse_mnemo_or_global_symbol_def(); } else { - Throw_error(exception_syntax); // FIXME - include char in error message! + throw_error(exception_syntax); // FIXME - include char in error message! parser_skip_remainder(); } } @@ -423,7 +421,7 @@ int parse_optional_block(void) parse_until_eob_or_eof(); if (GotByte != CHAR_EOB) - Throw_serious_error(exception_no_right_brace); + throw_serious_error(exception_no_right_brace); GetByte(); return TRUE; } @@ -451,7 +449,7 @@ void parse_source_code_file(FILE *fd, const char *eternal_plat_filename) // parse block and check end reason parse_until_eob_or_eof(); if (GotByte != CHAR_EOF) - Throw_error("Expected EOF, found '}' instead." ); + throw_error("Expected EOF, found '}' instead." ); // restore outer input inputchange_back(&icb); @@ -476,7 +474,7 @@ bits parser_get_force_bit(void) if (force_bit) GetByte(); else - Throw_error("Illegal postfix."); + throw_error("Illegal postfix."); } SKIPSPACE(); return force_bit; @@ -489,7 +487,7 @@ bits parser_get_force_bit(void) // errors. It shows the given message string, as well as the current // context: file name, line number, source type and source title. // if the "optional alternative location" given is NULL, the current location is used -static void throw_msg(const char *message, const char *ansicolor, const char *type, struct location *opt_alt_loc) +static void print_msg(const char *message, const char *ansicolor, const char *type, struct location *opt_alt_loc) { const char *resetcolor = "\033[0m"; struct location location; @@ -531,14 +529,14 @@ void throw_message(enum debuglevel level, const char msg[], struct location *opt // output a serious error // (assembly stops, for example if outbuffer overruns). PLATFORM_SERIOUS(msg); - throw_msg(msg, "\033[1m\033[31m", "Serious error", opt_alt_loc); // bold + red + print_msg(msg, "\033[1m\033[31m", "Serious error", opt_alt_loc); // bold + red //++pass.counters.errors; // FIXME - needed when problem below is solved exit(ACME_finalize(EXIT_FAILURE)); // FIXME - this inhibits output of macro call stack case DEBUGLEVEL_ERROR: // output an error // (something is wrong, no output file will be generated). PLATFORM_ERROR(msg); - throw_msg(msg, "\033[31m", "Error", opt_alt_loc); // red + print_msg(msg, "\033[31m", "Error", opt_alt_loc); // red ++pass.counters.errors; if (pass.counters.errors >= config.max_errors) exit(ACME_finalize(EXIT_FAILURE)); @@ -550,7 +548,7 @@ void throw_message(enum debuglevel level, const char msg[], struct location *opt if (in_nowarn_block || (statement_flags & SF_NOWARN_PREFIX)) break; PLATFORM_WARNING(msg); - throw_msg(msg, "\033[33m", "Warning", opt_alt_loc); // yellow + print_msg(msg, "\033[33m", "Warning", opt_alt_loc); // yellow ++pass.counters.warnings; // then check if warnings should be handled like errors: if (config.all_warnings_are_errors) { @@ -560,15 +558,53 @@ void throw_message(enum debuglevel level, const char msg[], struct location *opt } break; case DEBUGLEVEL_INFO: - throw_msg(msg, "\033[32m", "Info", opt_alt_loc); // green + PLATFORM_INFO(msg); + print_msg(msg, "\033[32m", "Info", opt_alt_loc); // green break; default: // debug - throw_msg(msg, "\033[36m", "Debug", opt_alt_loc); // cyan + print_msg(msg, "\033[36m", "Debug", opt_alt_loc); // cyan break; } } +// output a warning (something looks wrong) +void throw_warning(const char msg[]) +{ + throw_message(DEBUGLEVEL_WARNING, msg, NULL); +} + +// output an error (something is wrong, no output file will be generated). +// the assembler will try to go on with the assembly, so the user gets to know +// about more than one of his typos at a time. +void throw_error(const char msg[]) +{ + throw_message(DEBUGLEVEL_ERROR, msg, NULL); +} + +// output a serious error (assembly stops, for example if outbuffer overruns). +extern void throw_serious_error(const char msg[]) +{ + throw_message(DEBUGLEVEL_SERIOUS, msg, NULL); +} + +// output a warning, but only if we are in first pass, otherwise suppress +// (only use this if using throw_finalpass_warning is impossible, +// for example in cases where the code is skipped in later passes) +void throw_pass1_warning(const char msg[]) +{ + if (pass.number == 1) + throw_warning(msg); +} + +// output a warning, but only if we are in final pass, otherwise suppress +// (for example "converted float to int for XOR" -> must be done in +// final pass because values might be undefined earlier!) +void throw_finalpass_warning(const char msg[]) +{ + if (pass.flags.is_final_pass) + throw_warning(msg); +} // throw "macro twice" error (FIXME - also use for "symbol twice"!) // first output a warning, then an error, this guarantees that ACME does not @@ -592,30 +628,28 @@ void throw_redef_error(struct location *old_def, const char msg[]) section_now->type = buffered_section_type; section_now->title = buffered_section_title; // show error with location of current definition - Throw_error(msg); + throw_error(msg); } - -// process error that might vanish if symbols change: -// if current pass is an "error output" pass, actually throw error. -// otherwise just increment counter to let mainloop know this pass wasn't successful. -void throw_symbol_error(const char *msg) -{ - // atm we just mimic the old behaviour. in future, do something like this: - //if (pass.is_error_pass) - Throw_error(msg); - //else - //++pass.symbol_errors; -} - - // handle bugs // FIXME - use a local buffer and sprintf/snprintf to put error code into message! void BUG(const char *message, int code) { - Throw_warning("Bug in ACME, code follows"); + throw_warning("Bug in ACME, code follows"); fprintf(stderr, "(0x%x:)", code); - Throw_serious_error(message); + throw_serious_error(message); +} + +// process error that might vanish if symbols change: +// if current pass is an "error output" pass, actually throw error. +// otherwise just increment counter to let mainloop know this pass wasn't successful. +void countorthrow_value_error(const char *msg) +{ + // atm we just mimic the old behaviour. in future, do something like this: + //if (pass.is_error_pass) + throw_error(msg); + //else + //++pass.counters.suppressed_errors; } @@ -652,7 +686,7 @@ void output_object(struct object *object, struct iter_context *iter) while (length--) iter->fn(iter->stringxor ^ encoding_encode_char(*(read++))); } else { - Throw_error("There's more than one character."); // see alu.c for the original of this error + throw_error("There's more than one character."); // see alu.c for the original of this error } } else { BUG("IllegalObjectType", 0); @@ -664,7 +698,7 @@ void output_object(struct object *object, struct iter_context *iter) void output_8(intval_t value) { if ((value < -0x80) || (value > 0xff)) - throw_symbol_error(exception_number_out_of_8b_range); + countorthrow_value_error(exception_number_out_of_8b_range); output_byte(value); } @@ -673,7 +707,7 @@ void output_8(intval_t value) void output_be16(intval_t value) { if ((value < -0x8000) || (value > 0xffff)) - throw_symbol_error(exception_number_out_of_16b_range); + countorthrow_value_error(exception_number_out_of_16b_range); output_byte(value >> 8); output_byte(value); } @@ -683,7 +717,7 @@ void output_be16(intval_t value) void output_le16(intval_t value) { if ((value < -0x8000) || (value > 0xffff)) - throw_symbol_error(exception_number_out_of_16b_range); + countorthrow_value_error(exception_number_out_of_16b_range); output_byte(value); output_byte(value >> 8); } @@ -693,7 +727,7 @@ void output_le16(intval_t value) void output_be24(intval_t value) { if ((value < -0x800000) || (value > 0xffffff)) - throw_symbol_error(exception_number_out_of_24b_range); + countorthrow_value_error(exception_number_out_of_24b_range); output_byte(value >> 16); output_byte(value >> 8); output_byte(value); @@ -704,7 +738,7 @@ void output_be24(intval_t value) void output_le24(intval_t value) { if ((value < -0x800000) || (value > 0xffffff)) - throw_symbol_error(exception_number_out_of_24b_range); + countorthrow_value_error(exception_number_out_of_24b_range); output_byte(value); output_byte(value >> 8); output_byte(value >> 16); @@ -721,7 +755,7 @@ void output_le24(intval_t value) void output_be32(intval_t value) { // if ((value < -0x80000000) || (value > 0xffffffff)) -// throw_symbol_error(exception_number_out_of_32b_range); +// countorthrow_value_error(exception_number_out_of_32b_range); output_byte(value >> 24); output_byte(value >> 16); output_byte(value >> 8); @@ -733,7 +767,7 @@ void output_be32(intval_t value) void output_le32(intval_t value) { // if ((value < -0x80000000) || (value > 0xffffffff)) -// throw_symbol_error(exception_number_out_of_32b_range); +// countorthrow_value_error(exception_number_out_of_32b_range); output_byte(value); output_byte(value >> 8); output_byte(value >> 16); diff --git a/src/global.h b/src/global.h index dd30d85..fa29637 100644 --- a/src/global.h +++ b/src/global.h @@ -110,15 +110,17 @@ struct pass { int undefineds; // counts undefined expression results (if this stops decreasing, next pass must list them as errors) //int needvalue; // counts undefined expression results actually needed for output (when this hits zero, we're done) FIXME - use int symbolchanges; // count symbol changes (if nonzero, another pass is needed) - int errors; - int warnings; - // FIXME - add a counter for "errors not reported because pass flags - // said so", because then we can read the value after all symbol changes - // have finally settled and know if the next pass is a victory lap or an - // error output pass. + int errors; // if nonzero -> stop after this pass + int warnings; // this is needed for showing macro call stack + //int suppressed_errors; // FIXME - this is for + // "errors not reported because pass flags said so", because + // then we can read the value after all symbol changes have + // finally settled and know if the next pass is a victory lap or + // an error output pass. } counters; struct { boolean complain_about_undefined; // will be FALSE until error pass is needed + boolean is_final_pass; // needed for warnings like "converted float to int for xor" boolean throw_segment_messages; // atm only used in pass 1, should be used in _last_ pass! boolean generate_output; // create output and/or report file } flags; @@ -211,29 +213,39 @@ extern bits parser_get_force_bit(void); // if the "optional alternative location" given is NULL, the current location is used extern void throw_message(enum debuglevel level, const char msg[], struct location *opt_alt_loc); -// output a warning (something looks wrong, like "label name starts with shift-space character") -#define Throw_warning(msg) throw_message(DEBUGLEVEL_WARNING, msg, NULL) +// output a warning (something looks wrong) +extern void throw_warning(const char msg[]); // output an error (something is wrong, no output file will be generated). // the assembler will try to go on with the assembly, so the user gets to know // about more than one of his typos at a time. -#define Throw_error(msg) throw_message(DEBUGLEVEL_ERROR, msg, NULL) +extern void throw_error(const char msg[]); + +// output a serious error (assembly stops, for example if outbuffer overruns). +extern void throw_serious_error(const char msg[]); + +// output a warning, but only if we are in first pass, otherwise suppress +// (only use this if using throw_finalpass_warning is impossible, +// for example in cases where the code is skipped in later passes) +extern void throw_pass1_warning(const char msg[]); + +// output a warning, but only if we are in final pass, otherwise suppress +// (for example "converted float to int for XOR" -> must be done in +// final pass because values might be undefined earlier!) +extern void throw_finalpass_warning(const char msg[]); // throw "macro twice" error (FIXME - also use for "symbol twice"!) // first output a warning, then an error, this guarantees that ACME does not // reach the maximum error limit inbetween. extern void throw_redef_error(struct location *old_def, const char msg[]); +// handle bugs +extern void BUG(const char *msg, int code); + // process error that might vanish if symbols change: // if current pass is an "error output" pass, actually throw error. // otherwise just increment counter to let mainloop know this pass wasn't successful. -extern void throw_symbol_error(const char *msg); - -// output a serious error (assembly stops, for example if outbuffer overruns). -#define Throw_serious_error(msg) throw_message(DEBUGLEVEL_SERIOUS, msg, NULL) - -// handle bugs -extern void BUG(const char *msg, int code); +extern void countorthrow_value_error(const char *msg); // insert object (in case of list, will iterate/recurse until done) struct iter_context { diff --git a/src/input.c b/src/input.c index d89b893..c3bbf0b 100644 --- a/src/input.c +++ b/src/input.c @@ -253,7 +253,7 @@ static char get_processed_from_file(void) default: // complain if byte is 0 - Throw_error("Source file contains illegal character."); // FIXME - throw some dynamic "did not expect XYZ character" error instead! + throw_error("Source file contains illegal character."); // FIXME - throw some dynamic "did not expect XYZ character" error instead! return (char) from_file; } case INPUTSTATE_SKIPBLANKS: @@ -372,19 +372,19 @@ static void subst_substitute(void) // now GotByte = '?' goto fail; // input_read_scope_and_symbol_name will have thrown error } if (tmp_symbol->object.type == NULL) { - Throw_error("Substitution symbol is undefined."); + throw_error("Substitution symbol is undefined."); // FIXME - set type to undefined int, just to make sure later refs via type do not crash! goto fail; } else if (tmp_symbol->object.type == &type_number) { if (tmp_symbol->object.u.number.ntype != NUMTYPE_INT) { - Throw_error("Substitution symbol is undefined or not integer."); + throw_error("Substitution symbol is undefined or not integer."); goto fail; } dynabuf_add_signed_long(subst_buffer, (long) tmp_symbol->object.u.number.val.intval); } else if (tmp_symbol->object.type == &type_string) { dynabuf_add_bytes(subst_buffer, tmp_symbol->object.u.string->payload, tmp_symbol->object.u.string->length); } else { - Throw_error("Substitution symbol is neither number nor string."); + throw_error("Substitution symbol is neither number nor string."); goto fail; } @@ -394,7 +394,7 @@ static void subst_substitute(void) // now GotByte = '?' if (GotByte == ')') { GetByte(); // eat ')' } else { - Throw_error("Substitution does not end with ')' character."); + throw_error("Substitution does not end with ')' character."); goto fail; } } @@ -522,7 +522,7 @@ static void get_quoted_byte(void) } // now check for end of statement if (GotByte == CHAR_EOS) - Throw_error("Quotes still open at end of line."); + throw_error("Quotes still open at end of line."); } // skip remainder of statement, for example on error @@ -555,7 +555,7 @@ void parser_ensure_EOS(void) // now GotByte = first char to test // FIXME - change quoting: do not assume char is printable! quote = (GotByte == '\'') ? '"' : '\''; // use single quotes, unless byte is a single quote (then use double quotes) sprintf(buf, "Expected end-of-statement, found %c%c%c instead.", quote, GotByte, quote); - Throw_error(buf); + throw_error(buf); parser_skip_remainder(); } } @@ -628,7 +628,7 @@ int input_unescape_dynabuf(void) break; // TODO - 'a' to BEL? others? default: - Throw_error("Unsupported backslash sequence."); // TODO - add unexpected character to error message? + throw_error("Unsupported backslash sequence."); // TODO - add unexpected character to error message? } GLOBALDYNABUF_CURRENT[write_index++] = byte; escaped = FALSE; @@ -668,7 +668,7 @@ static void block_to_dynabuf(void) // now check for some special characters switch (byte) { case CHAR_EOF: // End-of-file in block? Sorry, no way. - Throw_serious_error(exception_no_right_brace); + throw_serious_error(exception_no_right_brace); case '"': // Quotes? Okay, read quoted stuff. case '\'': @@ -725,7 +725,7 @@ static int append_keyword_to_global_dynabuf(void) GetByte(); } if (length == 0) - Throw_error(exception_missing_string); + throw_error(exception_missing_string); return length; } @@ -741,7 +741,7 @@ int input_append_symbol_name_to_global_dynabuf(void) GetByte(); } else if (!BYTE_STARTS_KEYWORD(GotByte)) { // FIXME - show invalid char in error message! - Throw_error(exception_missing_string); + throw_error(exception_missing_string); return 1; // error } return append_keyword_to_global_dynabuf() == 0; // zero length -> error! @@ -822,7 +822,7 @@ static int read_filename_shared_end(boolean *absolute) { // check length if (GlobalDynaBuf->size == 0) { - Throw_error("No file name given."); + throw_error("No file name given."); return 1; // error } @@ -871,7 +871,7 @@ int input_read_input_filename(struct filespecflags *flags) flags->uses_lib = FALSE; // old algo (do not merge with similar parts from "if" block!): if (GotByte != '"') { - Throw_error("File name quotes not found (\"\" or <>)."); + throw_error("File name quotes not found (\"\" or <>)."); return 1; // error } // read file name string @@ -913,7 +913,7 @@ int parser_expect(int chr) GetByte(); // eat expected char return TRUE; } - Throw_error(exception_syntax); // FIXME - build "expected X, found Y" error msg! + throw_error(exception_syntax); // FIXME - build "expected X, found Y" error msg! return FALSE; } @@ -943,7 +943,7 @@ static void library_path_to_pathbuf(void) dynabuf_clear(pathbuf); lib_prefix = PLATFORM_LIBPREFIX; if ((PLATFORM_NEEDS_ENV_VAR) && (lib_prefix == NULL)) { - Throw_error("\"ACME\" environment variable not found."); + throw_error("\"ACME\" environment variable not found."); } else { dynabuf_add_string(pathbuf, lib_prefix); } @@ -995,11 +995,11 @@ int input_read_output_filename(void) SKIPSPACE(); if (GotByte == '<') { - Throw_error("Writing to library not supported."); + throw_error("Writing to library not supported."); return 1; // error } if (GotByte != '"') { - Throw_error("File name quotes not found (\"\")."); + throw_error("File name quotes not found (\"\")."); return 1; // error } dynabuf_clear(GlobalDynaBuf); @@ -1213,7 +1213,7 @@ FILE *includepaths_open_ro(struct filespecflags *flags) dynabuf_append(pathbuf, flags->uses_lib ? '>' : '\"'); dynabuf_append(pathbuf, '.'); dynabuf_append(pathbuf, '\0'); - Throw_error(pathbuf->buffer); + throw_error(pathbuf->buffer); } //fprintf(stderr, "File is [%s]\n", GLOBALDYNABUF_CURRENT); return stream; diff --git a/src/macro.c b/src/macro.c index d5f4383..59c1302 100644 --- a/src/macro.c +++ b/src/macro.c @@ -60,7 +60,7 @@ static void enlarge_arg_table(void) //printf("Doubling arg table size to %d.\n", argtable_size); arg_table = realloc(arg_table, argtable_size * sizeof(*arg_table)); if (arg_table == NULL) - Throw_serious_error(exception_no_memory_left); + throw_serious_error(exception_no_memory_left); } // Read macro scope and title. Title is read to GlobalDynaBuf and then copied @@ -149,7 +149,7 @@ void macro_parse_definition(void) // Now GotByte = illegal char after "!macro" } while (pipe_comma()); // ensure CHAR_SOB ('{') if (GotByte != CHAR_SOB) - Throw_serious_error(exception_no_left_brace); + throw_serious_error(exception_no_left_brace); } dynabuf_append(GlobalDynaBuf, CHAR_EOS); // terminate param list // now GlobalDynaBuf = comma-separated parameter list without spaces, @@ -197,7 +197,7 @@ void macro_parse_call(void) // Now GotByte = first char of macro name // Enter deeper nesting level // Quit program if recursion too deep. if (--sanity.macro_recursions_left < 0) - Throw_serious_error("Too deeply nested. Recursive macro calls?"); + throw_serious_error("Too deeply nested. Recursive macro calls?"); macro_scope = get_scope_and_title(); // now GotByte = first non-space after title // internal_name = MacroTitle ARG_SEPARATOR (grows to signature) @@ -234,7 +234,7 @@ void macro_parse_call(void) // Now GotByte = first char of macro name // Search for macro. Do not create if not found. search_for_macro(¯o_node, macro_scope, FALSE); if (macro_node == NULL) { - Throw_error("Macro not defined (or wrong signature)."); + throw_error("Macro not defined (or wrong signature)."); parser_skip_remainder(); } else { // make macro_node point to the macro struct @@ -269,7 +269,7 @@ void macro_parse_call(void) // Now GotByte = first char of macro name if (tree_hard_scan(&symbol_node, symbols_forest, symbol_scope, TRUE) == FALSE) { // we expect it to exist in later passes, but in pass 1 it's an error: if (pass.number == 1) - Throw_error("Macro parameter twice."); + throw_error("Macro parameter twice."); } symbol_node->body = arg_table[arg_count].symbol; // CAUTION, object type may be NULL } else { @@ -301,7 +301,7 @@ void macro_parse_call(void) // Now GotByte = first char of macro name // if needed, dump call stack if (outer_msg_sum != pass.counters.warnings + pass.counters.errors) - Throw_warning("...called from here."); + throw_warning("...called from here."); // FIXME - use DEBUGLEVEL_INFO instead! parser_ensure_EOS(); } diff --git a/src/mnemo.c b/src/mnemo.c index f874ad1..5ecdec2 100644 --- a/src/mnemo.c +++ b/src/mnemo.c @@ -571,7 +571,7 @@ static int get_index(void) NEXTANDSKIPSPACE(); return INDEX_Z; } - Throw_error("Expected index register after comma."); + throw_error("Expected index register after comma."); return INDEX_NONE; } @@ -584,8 +584,7 @@ static void get_int_arg(struct number *result, boolean complain_about_indirect) ALU_addrmode_int(&expression, 0); // accept 0 parentheses still open (-> complain!) if (expression.is_parenthesized && complain_about_indirect) { // TODO - raise error and be done with it? - if (pass.number == 1) - Throw_warning("There are unneeded parentheses, you know indirect addressing is impossible here, right?"); // FIXME - rephrase? add to docs! + throw_finalpass_warning("There are unneeded parentheses, you know indirect addressing is impossible here, right?"); // FIXME - rephrase? add to docs! } *result = expression.result.u.number; } @@ -652,11 +651,11 @@ static void check_oversize(bits size_bit, struct number *argument) if (size_bit == NUMBER_FORCES_16) { // check 16-bit argument for high byte zero if ((argument->val.intval <= 255) && (argument->val.intval >= -128)) - Throw_warning(exception_oversized_addrmode); + throw_finalpass_warning(exception_oversized_addrmode); } else { // check 24-bit argument for bank byte zero if ((argument->val.intval <= 65535) && (argument->val.intval >= -32768)) - Throw_warning(exception_oversized_addrmode); + throw_finalpass_warning(exception_oversized_addrmode); } } } @@ -674,7 +673,7 @@ static bits calc_arg_size(bits force_bit, struct number *argument, bits addressi { // if there are no possible addressing modes, complain if (addressing_modes == MAYBE______) { - Throw_error(exception_illegal_combination); + throw_error(exception_illegal_combination); return 0; } // if a force bit postfix was given, act upon it @@ -684,7 +683,7 @@ static bits calc_arg_size(bits force_bit, struct number *argument, bits addressi return force_bit; // if not, complain - Throw_error("CPU does not support this postfix for this mnemonic."); + throw_error("CPU does not support this postfix for this mnemonic."); return 0; } @@ -701,7 +700,7 @@ static bits calc_arg_size(bits force_bit, struct number *argument, bits addressi if (NUMBER_FORCES_24 & addressing_modes) return NUMBER_FORCES_24; - Throw_error(exception_number_out_of_range); // else error + throw_error(exception_number_out_of_range); // else error return 0; } @@ -744,7 +743,7 @@ static bits calc_arg_size(bits force_bit, struct number *argument, bits addressi // Value is sure, so use its own size // if value is negative, size cannot be chosen. Complain! if (argument->val.intval < 0) { - throw_symbol_error("Negative value - cannot choose addressing mode."); + countorthrow_value_error("Negative value - cannot choose addressing mode."); return 0; } @@ -766,7 +765,7 @@ static bits calc_arg_size(bits force_bit, struct number *argument, bits addressi } // Value is too big for all possible addressing modes - throw_symbol_error(exception_number_out_of_range); + countorthrow_value_error(exception_number_out_of_range); return 0; } @@ -777,8 +776,7 @@ static void group_only_implied_addressing(int opcode) // TODO - accept argument and complain about it? error message should tell more than "garbage data at end of line"! // for 65ce02 and 4502, warn about buggy decimal mode if ((opcode == 0xf8) && (cpu_current_type->flags & CPUFLAG_DECIMALSUBTRACTBUGGY)) { - if (pass.number == 1) - Throw_warning("Found SED instruction for CPU with known decimal SBC bug."); + throw_finalpass_warning("Found SED instruction for CPU with known decimal SBC bug."); } output_byte(opcode); parser_ensure_EOS(); @@ -790,7 +788,7 @@ static void not_in_bank(intval_t target) char buffer[60]; // 640K should be enough for anybody sprintf(buffer, "Target not in bank (0x%lx).", (long) target); - throw_symbol_error(buffer); + countorthrow_value_error(buffer); } // helper function for branches with 8-bit offset (including bbr0..7/bbs0..7) @@ -816,7 +814,7 @@ static void near_branch(int preoffset) char buffer[60]; // 640K should be enough for anybody sprintf(buffer, "Target out of range (%ld; %ld too far).", (long) offset, (long) (offset < -128 ? -128 - offset : offset - 127)); - throw_symbol_error(buffer); + countorthrow_value_error(buffer); } } } @@ -917,7 +915,7 @@ static void check_zp_wraparound(struct number *result) if ((result->ntype == NUMTYPE_INT) && (result->val.intval == 0xff) && (cpu_current_type->flags & CPUFLAG_WARN_ABOUT_FF_PTR)) - Throw_warning("Zeropage pointer wraps around from $ff to $00"); + throw_finalpass_warning("Zeropage pointer wraps around from $ff to $00"); } // The main accumulator stuff (ADC, AND, CMP, EOR, LDA, ORA, SBC, STA) @@ -981,7 +979,7 @@ static void group_main(int index, bits flags) make_instruction(force_bit, &result, accu_lindz8[index]); break; default: // other combinations are illegal - Throw_error(exception_illegal_combination); + throw_error(exception_illegal_combination); } } @@ -997,7 +995,7 @@ static void group_misc(int index, bits immediate_mode) if (misc_impl[index]) output_byte(misc_impl[index]); else - Throw_error(exception_illegal_combination); + throw_error(exception_illegal_combination); break; case IMMEDIATE_ADDRESSING: // #$ff or #$ffff (depending on index register length) immediate_opcodes = imm_ops(&force_bit, misc_imm[index], immediate_mode); @@ -1009,9 +1007,9 @@ static void group_misc(int index, bits immediate_mode) && (result.ntype == NUMTYPE_INT) && (result.val.intval != 0x00)) { if (immediate_opcodes == 0x8b) - Throw_warning("Assembling unstable ANE #NONZERO instruction"); + throw_finalpass_warning("Assembling unstable ANE #NONZERO instruction"); else if (immediate_opcodes == 0xab) - Throw_warning("Assembling unstable LXA #NONZERO instruction"); + throw_finalpass_warning("Assembling unstable LXA #NONZERO instruction"); } break; case ABSOLUTE_ADDRESSING: // $ff or $ffff @@ -1024,7 +1022,7 @@ static void group_misc(int index, bits immediate_mode) make_instruction(force_bit, &result, misc_yabs[index]); break; default: // other combinations are illegal - Throw_error(exception_illegal_combination); + throw_error(exception_illegal_combination); } } @@ -1096,7 +1094,7 @@ static void group_mvn_mvp(int opcode) output_8(source.val.intval); // sanity check if (unmatched_hash) - Throw_error(exception_syntax); // FIXME - maybe "Use ARG,ARG or #ARG,#ARG but do not mix and match"? + throw_error(exception_syntax); // FIXME - maybe "Use ARG,ARG or #ARG,#ARG but do not mix and match"? parser_ensure_EOS(); } @@ -1120,7 +1118,7 @@ static void group_prefix(int opcode) char buffer[100]; // 640K should be enough for anybody sprintf(buffer, "The chosen CPU uses opcode 0x%02x as a prefix code, do not use this mnemonic!", opcode); - Throw_error(buffer); + throw_error(buffer); } // The jump instructions. @@ -1139,7 +1137,7 @@ static void group_jump(int index) if ((result.ntype == NUMTYPE_INT) && ((result.val.intval & 0xff) == 0xff) && (cpu_current_type->flags & CPUFLAG_INDIRECTJMPBUGGY)) - Throw_warning("Assembling buggy JMP($xxff) instruction"); + throw_finalpass_warning("Assembling buggy JMP($xxff) instruction"); break; case X_INDEXED_INDIRECT_ADDRESSING: // ($ffff,x) make_instruction(force_bit, &result, jump_xind[index]); @@ -1148,7 +1146,7 @@ static void group_jump(int index) make_instruction(force_bit, &result, jump_lind[index]); break; default: // other combinations are illegal - Throw_error(exception_illegal_combination); + throw_error(exception_illegal_combination); } } diff --git a/src/output.c b/src/output.c index 05d9f10..7a27eb6 100644 --- a/src/output.c +++ b/src/output.c @@ -105,7 +105,7 @@ static void border_crossed(int current_offset) // so it can be suppressed until we are sure the program won't shrink any // further: if (current_offset >= OUTBUF_MAXSIZE) - Throw_serious_error("Reached memory limit."); + throw_serious_error("Reached memory limit."); if (pass.flags.throw_segment_messages) { throw_message(config.debuglevel_segmentprobs, "Segment reached another one, overwriting it.", NULL); find_segment_max(current_offset + 1); // find new (next) limit @@ -148,7 +148,7 @@ static void real_output(intval_t byte) // not happen again static void complain_and_use_dummy_pc(void) { - Throw_error(exception_pc_undefined); + throw_error(exception_pc_undefined); programcounter_set(cpu_current_type->dummy_pc, 0); // 0 = no flags } @@ -287,7 +287,7 @@ void output_passinit(void) out->needed_bufsize = 16; // actually 1 would suffice... } if (out->needed_bufsize > OUTBUF_MAXSIZE) { - Throw_serious_error("Output buffer size exceeds maximum."); + throw_serious_error("Output buffer size exceeds maximum."); } //fprintf(stderr, "Allocating outbuf of size 0x%06x.\n", out->needed_bufsize); out->buffer = safe_malloc(out->needed_bufsize); @@ -404,9 +404,9 @@ static void start_segment(intval_t address_change, bits segment_flags) // calculate start of new segment out->write_idx = out->write_idx + address_change; if (out->write_idx < 0) { - Throw_serious_error("Tried to write to negative addresses."); + throw_serious_error("Tried to write to negative addresses."); } else if (out->write_idx >= OUTBUF_MAXSIZE) { - Throw_serious_error("Reached memory limit."); + throw_serious_error("Reached memory limit."); } out->segm.start = out->write_idx; out->segm.flags = segment_flags; @@ -556,11 +556,11 @@ int pseudopc_unpseudo(struct number *target, struct pseudopc *context, unsigned return 0; // ok (no sense in trying to unpseudo this, and it might be an unresolved forward ref anyway) if (context == NULL) { - Throw_error("Un-pseudopc operator '&' only works on addresses."); + throw_error("Un-pseudopc operator '&' only works on addresses."); return 1; // error } if (context == &outermost_pseudopc_context) { - Throw_error("Un-pseudopc operator '&' has no !pseudopc context."); + throw_error("Un-pseudopc operator '&' has no !pseudopc context."); return 1; // error } target->val.intval = target->val.intval - context->offset; // remove offset diff --git a/src/pseudoopcodes.c b/src/pseudoopcodes.c index acad195..c1f98b3 100644 --- a/src/pseudoopcodes.c +++ b/src/pseudoopcodes.c @@ -57,7 +57,7 @@ static enum eos po_initmem(void) // the "--initmem" cli arg and earlier calls have priority if (config.mem_init_value != NO_VALUE_GIVEN) { - Throw_warning("Memory already initialised."); + throw_pass1_warning("Memory already initialised."); return SKIP_REMAINDER; } @@ -67,7 +67,7 @@ static enum eos po_initmem(void) // first pass) ALU_defined_int(&intresult); if ((intresult.val.intval > 255) || (intresult.val.intval < -128)) - Throw_error(exception_number_out_of_8b_range); + throw_error(exception_number_out_of_8b_range); // remember value config.mem_init_value = intresult.val.intval & 0xff; @@ -86,7 +86,7 @@ static enum eos po_to(void) // the "--outfile" cli arg and earlier calls have priority if (config.output_filename) { - Throw_warning("Output file name already chosen."); + throw_pass1_warning("Output file name already chosen."); return SKIP_REMAINDER; } @@ -107,20 +107,20 @@ static enum eos po_to(void) format = outputformat_find(); if (format == OUTFILE_FORMAT_UNSPECIFIED) { - Throw_error("Unknown output format."); + throw_error("Unknown output format."); return SKIP_REMAINDER; } } else { // no comma: complain unless user requested really old behaviour if (config.dialect >= V0_86__DEPRECATE_REALPC) - Throw_warning("Used \"!to\" without file format indicator."); + throw_pass1_warning("Used \"!to\" without file format indicator."); // default to cbm format = OUTFILE_FORMAT_CBM; } // the "--format" cli arg has priority if (config.outfile_format != OUTFILE_FORMAT_UNSPECIFIED) { - Throw_warning("Output file format already chosen."); + throw_pass1_warning("Output file format already chosen."); } else { config.outfile_format = format; } @@ -137,7 +137,7 @@ static enum eos po_symbollist(void) // cli arg and earlier calls have priority if (config.symbollist_filename) { - Throw_warning("Symbol list file name already chosen."); + throw_pass1_warning("Symbol list file name already chosen."); return SKIP_REMAINDER; } @@ -163,8 +163,7 @@ static enum eos po_outfilestart(void) if ((config.outfile_start != NO_VALUE_GIVEN) || (last_pass_number == pass.number)) { - if (pass.number == 1) - Throw_warning("Start of output file already chosen."); + throw_pass1_warning("Start of output file already chosen."); } else { last_pass_number = pass.number; outbuf_set_outfile_start(); @@ -179,8 +178,7 @@ static enum eos po_outfilelimit(void) if ((config.outfile_limit != NO_VALUE_GIVEN) || (last_pass_number == pass.number)) { - if (pass.number == 1) - Throw_warning("End of output file already chosen."); + throw_pass1_warning("End of output file already chosen."); } else { last_pass_number = pass.number; outbuf_set_outfile_limit(); @@ -202,7 +200,7 @@ static enum eos po_xor(void) old_value = output_get_xor(); ALU_any_int(&change); if ((change > 255) || (change < -128)) { - Throw_error(exception_number_out_of_8b_range); + throw_error(exception_number_out_of_8b_range); change = 0; } output_set_xor(old_value ^ change); @@ -321,7 +319,7 @@ static enum eos po_hex(void) // now GotByte = illegal char // if we're here, the current character is not a hex digit, // which is only allowed outside of pairs: if (digits == 1) { - Throw_error("Hex digits are not given in pairs."); + throw_error("Hex digits are not given in pairs."); return SKIP_REMAINDER; // error exit } switch (GotByte) { @@ -332,7 +330,7 @@ static enum eos po_hex(void) // now GotByte = illegal char case CHAR_EOS: return AT_EOS_ANYWAY; // normal exit default: - Throw_error(exception_syntax); // FIXME - include character in error message! + throw_error(exception_syntax); // FIXME - include character in error message! return SKIP_REMAINDER; // error exit } } @@ -343,11 +341,10 @@ static enum eos po_hex(void) // now GotByte = illegal char static enum eos po_cbm(void) { if (config.dialect >= V0_94_8__DISABLED_OBSOLETE) { - Throw_error("\"!cbm\" is obsolete; use \"!ct pet\" instead."); + throw_error("\"!cbm\" is obsolete; use \"!ct pet\" instead."); } else { encoder_current = &encoder_pet; - if (pass.number == 1) - Throw_warning("\"!cbm\" is deprecated; use \"!ct pet\" instead."); + throw_finalpass_warning("\"!cbm\" is deprecated; use \"!ct pet\" instead."); } return ENSURE_EOS; } @@ -371,7 +368,7 @@ static enum eos use_encoding_from_file(void) if (stream) { // try to load encoding table from given file if (fread(local_table, sizeof(char), 256, stream) != 256) - Throw_error("Conversion table incomplete."); + throw_error("Conversion table incomplete."); fclose(stream); } @@ -445,7 +442,7 @@ static enum eos po_convtab(void) return use_encoding_from_file(); } - Throw_error("Unknown encoding."); + throw_error("Unknown encoding."); return use_predefined_encoding(encoder_current); // keep going } // insert string(s) @@ -555,7 +552,7 @@ static enum eos po_binary(void) // then parse it ALU_defined_int(&size); if (size.val.intval < 0) - Throw_serious_error(exception_negative_size); + throw_serious_error(exception_negative_size); } // more? if (parser_accept_comma()) { @@ -585,7 +582,7 @@ static enum eos po_binary(void) } // if more should have been read, warn and add padding if (size.val.intval > 0) { - Throw_warning("Padding with zeroes."); + throw_warning("Padding with zeroes."); do { output_byte(0); } while (--size.val.intval); @@ -625,7 +622,7 @@ static enum eos po_skip(void) // now GotByte = illegal char ALU_defined_int(&amount); // FIXME - forbid addresses! if (amount.val.intval < 0) - Throw_serious_error(exception_negative_size); // TODO - allow this? + throw_serious_error(exception_negative_size); // TODO - allow this? else output_skip(amount.val.intval); return ENSURE_EOS; @@ -656,7 +653,7 @@ static enum eos po_align(void) // make sure PC is defined programcounter_read(&pc); if (pc.ntype == NUMTYPE_UNDEFINED) { - Throw_error(exception_pc_undefined); + throw_error(exception_pc_undefined); return SKIP_REMAINDER; } @@ -671,11 +668,10 @@ static void old_offset_assembly(void) { if (config.dialect >= V0_94_8__DISABLED_OBSOLETE) { // now it's obsolete - Throw_error("\"!pseudopc/!realpc\" are obsolete; use \"!pseudopc {}\" instead."); // FIXME - amend msg, tell user how to use old behaviour! + throw_error("\"!pseudopc/!realpc\" are obsolete; use \"!pseudopc {}\" instead."); // FIXME - amend msg, tell user how to use old behaviour! } else if (config.dialect >= V0_86__DEPRECATE_REALPC) { // earlier it was deprecated - if (pass.number == 1) - Throw_warning("\"!pseudopc/!realpc\" are deprecated; use \"!pseudopc {}\" instead."); + throw_finalpass_warning("\"!pseudopc/!realpc\" are deprecated; use \"!pseudopc {}\" instead."); } else { // really old versions allowed it } @@ -703,13 +699,13 @@ static enum eos po_pseudopc(void) skip '=' read segment name (quoted string!) } else { - Throw_error("Unknown !pseudopc segment modifier."); + throw_error("Unknown !pseudopc segment modifier."); return SKIP_REMAINDER; } } */ if (new_pc.val.intval < 0) { - Throw_error("Program counter cannot be negative."); + throw_error("Program counter cannot be negative."); new_pc.val.intval = cpu_current_type->dummy_pc; } pseudopc_start(&new_pc); @@ -756,7 +752,7 @@ static enum eos po_cpu(void) if (new_cpu_type) cpu_current_type = new_cpu_type; // activate new cpu type else - Throw_error("Unknown processor."); + throw_error("Unknown processor."); } // if there's a block, parse that and then restore old value if (parse_optional_block()) @@ -808,7 +804,7 @@ static enum eos po_enum(void) // now GotByte = illegal char step.val.intval = 1; ALU_defined_int(&step); -Throw_serious_error("Not yet"); // FIXME +throw_serious_error("Not yet"); // FIXME return ENSURE_EOS; } #endif @@ -879,10 +875,9 @@ static enum eos po_zone(void) static enum eos po_subzone(void) { if (config.dialect >= V0_94_8__DISABLED_OBSOLETE) { - Throw_error("\"!subzone {}\" is obsolete; use \"!zone {}\" instead."); + throw_error("\"!subzone {}\" is obsolete; use \"!zone {}\" instead."); } else { - if (pass.number == 1) - Throw_warning("\"!subzone {}\" is deprecated; use \"!zone {}\" instead."); + throw_finalpass_warning("\"!subzone {}\" is deprecated; use \"!zone {}\" instead."); } // call "!zone" instead return po_zone(); @@ -898,7 +893,7 @@ static enum eos po_source(void) // now GotByte = illegal char // enter new nesting level // quit program if recursion too deep if (--sanity.source_recursions_left < 0) - Throw_serious_error("Too deeply nested. Recursive \"!source\"?"); + throw_serious_error("Too deeply nested. Recursive \"!source\"?"); // read file name and convert from UNIX style to platform style if (input_read_input_filename(&flags)) @@ -937,7 +932,7 @@ static enum eos ifelse(enum ifmode mode) ALU_defined_int(&ifresult); condition_met = !!ifresult.val.intval; if (GotByte != CHAR_SOB) - Throw_serious_error(exception_no_left_brace); + throw_serious_error(exception_no_left_brace); break; case IFMODE_IFDEF: condition_met = check_ifdef_condition(); @@ -960,7 +955,7 @@ static enum eos ifelse(enum ifmode mode) parse_until_eob_or_eof(); // parse block // if block isn't correctly terminated, complain and exit if (GotByte != CHAR_EOB) - Throw_serious_error(exception_no_right_brace); + throw_serious_error(exception_no_right_brace); } else { return PARSE_REMAINDER; // parse line (only for ifdef/ifndef) } @@ -977,7 +972,7 @@ static enum eos ifelse(enum ifmode mode) if (mode == IFMODE_ELSE) { // we could just return ENSURE_EOS, but checking here allows for better error message if (GotByte != CHAR_EOS) - Throw_error("Expected end-of-statement after ELSE block."); + throw_error("Expected end-of-statement after ELSE block."); return SKIP_REMAINDER; // normal exit after ELSE {...} } @@ -991,7 +986,7 @@ static enum eos ifelse(enum ifmode mode) // make sure it's "else" if (strcmp(GlobalDynaBuf->buffer, "else")) { - Throw_error("Expected end-of-statement or ELSE keyword after '}'."); + throw_error("Expected end-of-statement or ELSE keyword after '}'."); return SKIP_REMAINDER; // an error has been reported, so ignore rest of line } // anything more? @@ -1014,7 +1009,7 @@ static enum eos ifelse(enum ifmode mode) } else if (strcmp(GlobalDynaBuf->buffer, "ifndef") == 0) { mode = IFMODE_IFNDEF; } else { - Throw_error("Expected '{' or IF/IFDEF/IFNDEF keyword after ELSE keyword."); + throw_error("Expected '{' or IF/IFDEF/IFNDEF keyword after ELSE keyword."); return SKIP_REMAINDER; // an error has been reported, so ignore rest of line } } @@ -1067,16 +1062,14 @@ static enum eos po_for(void) // now GotByte = illegal char // new counter syntax loop.algorithm = FORALGO_NEWCOUNT; if (config.dialect < V0_94_12__NEW_FOR_SYNTAX) { - if (pass.number == 1) - Throw_warning("Found new \"!for\" syntax."); + throw_finalpass_warning("Found new \"!for\" syntax."); } loop.u.counter.first = intresult.val.intval; // use first argument ALU_defined_int(&intresult); // read second argument // compare addr_ref counts and complain if not equal! if (config.warn_on_type_mismatch && (intresult.addr_refs != loop.u.counter.addr_refs)) { - if (pass.number == 1) - Throw_warning("Wrong type for loop's END value - must match type of START value."); + throw_finalpass_warning("Wrong type for loop's END value - must match type of START value."); } // setup direction and total if (loop.u.counter.first <= intresult.val.intval) { @@ -1092,11 +1085,10 @@ static enum eos po_for(void) // now GotByte = illegal char // old counter syntax loop.algorithm = FORALGO_OLDCOUNT; if (config.dialect >= V0_94_12__NEW_FOR_SYNTAX) { - if (pass.number == 1) - Throw_warning("Found old \"!for\" syntax."); + throw_finalpass_warning("Found old \"!for\" syntax."); } if (intresult.val.intval < 0) { - Throw_serious_error("Loop count is negative."); + throw_serious_error("Loop count is negative."); } // count up loop.u.counter.first = 1; @@ -1108,11 +1100,11 @@ static enum eos po_for(void) // now GotByte = illegal char loop.algorithm = FORALGO_ITERATE; // check for "in" keyword if ((GotByte != 'i') && (GotByte != 'I')) { - Throw_error(exception_want_IN_or_comma); + throw_error(exception_want_IN_or_comma); return SKIP_REMAINDER; // FIXME - this ignores '{' and will then complain about '}' } /* checking for the first character explicitly here looks dumb, but actually -solves a purpose: we're here because the check for comma failed, but maybe that +serves a purpose: we're here because the check for comma failed, but maybe that was just a typo. if the current byte is '.' or '-' or whatever, then trying to read a keyword will result in "No string given" - which is confusing for the user if they did not even want to put a string there. @@ -1121,23 +1113,23 @@ knowing there is an "i" also makes sure that parser_read_and_lower_keyword() does not fail. */ parser_read_and_lower_keyword(); if (strcmp(GlobalDynaBuf->buffer, "in") != 0) { - Throw_error(exception_want_IN_or_comma); + throw_error(exception_want_IN_or_comma); return SKIP_REMAINDER; // FIXME - this ignores '{' and will then complain about '}' } if (force_bit) { - Throw_error("Force bits can only be given to counters, not when iterating over string/list contents."); + throw_error("Force bits can only be given to counters, not when iterating over string/list contents."); return SKIP_REMAINDER; // FIXME - this ignores '{' and will then complain about '}' } ALU_any_result(&loop.u.iter.obj); // get iterable loop.iterations_left = loop.u.iter.obj.type->length(&loop.u.iter.obj); if (loop.iterations_left < 0) { - Throw_error("Given object is not iterable."); + throw_error("Given object is not iterable."); return SKIP_REMAINDER; // FIXME - this ignores '{' and will then complain about '}' } } if (GotByte != CHAR_SOB) - Throw_serious_error(exception_no_left_brace); + throw_serious_error(exception_no_left_brace); input_block_getcopy(&loop.block); // "body" must be freed afterward... flow_forloop(&loop); @@ -1158,7 +1150,7 @@ static enum eos po_do(void) // now GotByte = illegal char SKIPSPACE(); flow_store_doloop_condition(&loop.head_cond, CHAR_SOB); // must be freed! if (GotByte != CHAR_SOB) - Throw_serious_error(exception_no_left_brace); + throw_serious_error(exception_no_left_brace); input_block_getcopy(&loop.block); // "body" must be freed! // now GotByte = '}' @@ -1184,7 +1176,7 @@ static enum eos po_while(void) // now GotByte = illegal char SKIPSPACE(); flow_store_while_condition(&loop.head_cond); // "body" must be freed! if (GotByte != CHAR_SOB) - Throw_serious_error(exception_no_left_brace); + throw_serious_error(exception_no_left_brace); // read block input_block_getcopy(&loop.block); // "body" must be freed! // clear tail condition @@ -1245,7 +1237,7 @@ static enum eos tracewatch(boolean enter_monitor) } else if (strcmp(GlobalDynaBuf->buffer, "exec") == 0) { flags |= TRACEWATCH_EXEC; } else { - Throw_error("Unknown flag (known are: load, store, exec)."); // FIXME - add to docs! + throw_error("Unknown flag (known are: load, store, exec)."); // FIXME - add to docs! return SKIP_REMAINDER; } } while (parser_accept_comma()); @@ -1501,7 +1493,7 @@ void pseudoopcode_parse(void) // now GotByte = '!' (or '.' in case of --fullstop // call function then = fn(); } else { - Throw_error("Unknown pseudo opcode."); + throw_error("Unknown pseudo opcode."); } } if (then == SKIP_REMAINDER) @@ -1550,7 +1542,7 @@ void notreallypo_setpc(void) // GotByte is '*' skip '=' read segment name (quoted string!) */ } else { - Throw_error("Unknown \"*=\" segment modifier."); + throw_error("Unknown \"*=\" segment modifier."); goto fail; } } @@ -1562,7 +1554,7 @@ void notreallypo_setpc(void) // GotByte is '*' // current behaviour: // setting pc does not disable pseudopc } else if (config.dialect >= V0_93__SHORTER_SETPC_WARNING) { - Throw_warning("Offset assembly still active at end of segment."); + throw_warning("Offset assembly still active at end of segment."); end_all_pseudopc(); // warning did not say it would // disable pseudopc, but still did. nevertheless, there // is something different to older versions: when the @@ -1570,13 +1562,13 @@ void notreallypo_setpc(void) // GotByte is '*' // stuff happens! i see no reason to try to mimic that. } else { // prior to 0.93, setting pc disabled pseudopc with a warning: - Throw_warning("Offset assembly still active at end of segment. Switched it off."); + throw_warning("Offset assembly still active at end of segment. Switched it off."); end_all_pseudopc(); } } if (intresult.val.intval < 0) { - Throw_error("Program counter cannot be negative."); + throw_error("Program counter cannot be negative."); intresult.val.intval = cpu_current_type->dummy_pc; } programcounter_set(intresult.val.intval, segment_flags); diff --git a/src/symbol.c b/src/symbol.c index c7d07b2..78f7b3a 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -154,7 +154,7 @@ void symbol_set_object(struct symbol *symbol, struct object *new_value, bits pow // if too different, needs power (or complains) if (symbol->object.type != new_value->type) { if (!(powers & POWER_CHANGE_OBJTYPE)) - Throw_error(exception_symbol_defined); + throw_error(exception_symbol_defined); // CAUTION: if above line throws error, we still go ahead and change type! // this is to keep "!for" working, where the counter var is accessed. symbol->object = *new_value; // copy whole struct including type @@ -182,7 +182,7 @@ void symbol_set_force_bit(struct symbol *symbol, bits force_bit) BUG("NullTypeObject", 0); if (symbol->object.type != &type_number) { - Throw_error("Force bits can only be given to numbers."); + throw_error("Force bits can only be given to numbers."); return; } @@ -195,7 +195,7 @@ void symbol_set_force_bit(struct symbol *symbol, bits force_bit) // it's too late to change, so check if the wanted bit is actually different if ((symbol->object.u.number.flags & NUMBER_FORCEBITS) != force_bit) - Throw_error("Too late for postfix."); + throw_error("Too late for postfix."); } diff --git a/src/typesystem.c b/src/typesystem.c index 49536f9..c859053 100644 --- a/src/typesystem.c +++ b/src/typesystem.c @@ -19,7 +19,7 @@ void typesystem_want_nonaddr(struct number *result) return; if (result->addr_refs != 0) { - Throw_warning("Wrong type - expected integer."); + throw_finalpass_warning("Wrong type - expected integer."); //printf("refcount should be 0, but is %d\n", result->addr_refs); } } @@ -34,7 +34,7 @@ void typesystem_want_addr(struct number *result) return; if (result->addr_refs != 1) { - Throw_warning("Wrong type - expected address."); + throw_finalpass_warning("Wrong type - expected address."); //printf("refcount should be 1, but is %d\n", result->addr_refs); } } diff --git a/src/version.h b/src/version.h index 8ba748d..a0a779a 100644 --- a/src/version.h +++ b/src/version.h @@ -9,7 +9,7 @@ #define RELEASE "0.97" // update before release FIXME #define CODENAME "Zem" // update before release -#define CHANGE_DATE "6 Aug" // update before release FIXME +#define CHANGE_DATE "7 Aug" // 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