diff --git a/README.md b/README.md index f7ba8f6..5089bc2 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,8 @@ Primarily tested with personal archive of sources written for Kick assmebler, DA * irp (indefinite repeat) **FIXED** +* Macros works within conditionals (if/else/endif, etc) +* String symbols broke late evaluation resulting in garbage references, this has been fixed * Added string symbols * Resolved the DirectPage_Stack section vs. Zeropage section for Apple II GS/OS executables. * OMF export for Apple II GS/OS executables diff --git a/bin/x65_win32.zip b/bin/x65_win32.zip index e75efa9..87bf889 100644 Binary files a/bin/x65_win32.zip and b/bin/x65_win32.zip differ diff --git a/bin/x65_x64.zip b/bin/x65_x64.zip index 2d4d817..25d8a9f 100644 Binary files a/bin/x65_x64.zip and b/bin/x65_x64.zip differ diff --git a/struse.h b/struse.h index 136e816..319ee30 100644 --- a/struse.h +++ b/struse.h @@ -2782,7 +2782,7 @@ int strref::find_last_bookend(const strref str, const strref bookend) const } } if (!left_check) { - if (string == scan_chk || bookend.char_matches_ranges(int_tolower_ascii7(*--cmp_chk))) + if (string == scan_chk || bookend.char_matches_ranges(int_tolower_ascii7(*--scan_chk))) return left - str.length + 1; } } @@ -4272,7 +4272,7 @@ strl_t _strmod_inplace_replace_bookend_int(char *string, strl_t length, strl_t c ps += ss; while (ss >= 0 && strl_t(ss)=MAX_CONDITIONAL_DEPTH) + return ERROR_CONDITION_TOO_NESTED; + conditional_depth++; + conditional_nesting[conditional_depth] = 0; + conditional_consumed[conditional_depth] = false; + contextStack.push(src_name, src_file, code_seg, rept); + contextStack.curr().conditional_ctx = conditional_depth; + return STATUS_OK; +} + +StatusCode Asm::PopContext() +{ + if (contextStack.curr().scoped_context && scope_depth) { + StatusCode ret = ExitScope(); + if (ret != STATUS_OK) + return ret; + } + if (!ConditionalAsm() || ConditionalConsumed() || + conditional_depth!=contextStack.curr().conditional_ctx) + return ERROR_UNTERMINATED_CONDITION; + + conditional_depth = contextStack.curr().conditional_ctx-1; + contextStack.pop(); + return STATUS_OK; +} + // // @@ -2836,7 +2878,7 @@ StatusCode Asm::BuildMacro(Macro &m, strref arg_list) macexp.replace_bookend(tag.get_strref(), a, label_end_char_range_merlin); } } - contextStack.push(m.source_name, macexp.get_strref(), macexp.get_strref()); + PushContext(m.source_name, macexp.get_strref(), macexp.get_strref()); if (scope_depth>=(MAX_SCOPE_DEPTH-1)) return ERROR_TOO_DEEP_SCOPE; else @@ -2869,9 +2911,9 @@ StatusCode Asm::BuildMacro(Macro &m, strref arg_list) strref a = arg_list.split_token_trim(token); macexp.replace_bookend(param, a, label_end_char_range); } - contextStack.push(m.source_name, macexp.get_strref(), macexp.get_strref()); + PushContext(m.source_name, macexp.get_strref(), macexp.get_strref()); if (end_macro_directive) { - contextStack.push(m.source_name, macexp.get_strref(), macexp.get_strref()); + PushContext(m.source_name, macexp.get_strref(), macexp.get_strref()); if (scope_depth>=(MAX_SCOPE_DEPTH-1)) return ERROR_TOO_DEEP_SCOPE; else @@ -2882,7 +2924,7 @@ StatusCode Asm::BuildMacro(Macro &m, strref arg_list) } else return ERROR_OUT_OF_MEMORY_FOR_MACRO_EXPANSION; } - contextStack.push(m.source_name, m.source_file, macro_src); + PushContext(m.source_name, m.source_file, macro_src); return STATUS_OK; } @@ -3203,7 +3245,7 @@ EvalOperator Asm::RPNToken(strref &exp, const struct EvalContext &etx, EvalOpera if (ret != STATUS_NOT_STRUCT) return EVOP_ERR; // partial struct } if (!pLabel && label.same_str("rept")) { value = etx.rept_cnt; return EVOP_VAL; } - if (!pLabel) { if (StringSymbol *pStr = GetString(label)) subexp = pStr->get(); return EVOP_EXP; } + if (!pLabel) { if (StringSymbol *pStr = GetString(label)) { subexp = pStr->get(); return EVOP_EXP; } } if (!pLabel || !pLabel->evaluated) return EVOP_NRY; // this label could not be found (yet) value = pLabel->value; section = pLabel->section; return pLabel->reference ? EVOP_XRF : EVOP_VAL; } @@ -4224,7 +4266,7 @@ StatusCode Asm::StringAction(StringSymbol *pStr, strref line) mac.copy(str); mac.replace("\\n", "\n"); loadedData.push_back(macro); - contextStack.push(contextStack.curr().source_name, mac.get_strref(), mac.get_strref()); + PushContext(contextStack.curr().source_name, mac.get_strref(), mac.get_strref()); if (scope_depth >= (MAX_SCOPE_DEPTH - 1)) return ERROR_TOO_DEEP_SCOPE; else @@ -4255,7 +4297,7 @@ bool Asm::NewConditional() { // Encountered #endif, close out the current conditional void Asm::CloseConditional() { - if (conditional_depth) + if (conditional_depth>contextStack.curr().conditional_ctx) conditional_depth--; else conditional_consumed[conditional_depth] = false; @@ -4419,7 +4461,7 @@ StatusCode Asm::Directive_Rept(strref line, strref source_file) } else recur = read_source.scoped_block_skip(); ctx.next_source = read_source; - contextStack.push(ctx.source_name, ctx.source_file, recur, count); + PushContext(ctx.source_name, ctx.source_file, recur, count); } return STATUS_OK; } @@ -4505,27 +4547,27 @@ StatusCode Asm::Directive_Include(strref line) if ((buffer = LoadText(file, size))) { loadedData.push_back(buffer); strref src(buffer, strl_t(size)); - contextStack.push(file, src, src); + PushContext(file, src, src); } else if (syntax == SYNTAX_MERLIN) { // MERLIN include file name rules if (file[0]>='!' && file[0]<='&' && (buffer = LoadText(file+1, size))) { loadedData.push_back(buffer); // MERLIN: prepend with !-& to not auto-prepend with T. strref src(buffer, strl_t(size)); - contextStack.push(file+1, src, src); + PushContext(file+1, src, src); } else { strown<512> fileadd(file[0]>='!' && file[0]<='&' ? (file+1) : file); fileadd.append(".s"); if ((buffer = LoadText(fileadd.get_strref(), size))) { loadedData.push_back(buffer); // MERLIN: !+filename appends .S to filenames strref src(buffer, strl_t(size)); - contextStack.push(file, src, src); + PushContext(file, src, src); } else { fileadd.copy("T."); // MERLIN: just filename prepends T. to filenames fileadd.append(file[0]>='!' && file[0]<='&' ? (file+1) : file); if ((buffer = LoadText(fileadd.get_strref(), size))) { loadedData.push_back(buffer); strref src(buffer, strl_t(size)); - contextStack.push(file, src, src); + PushContext(file, src, src); } } } @@ -5745,13 +5787,13 @@ StatusCode Asm::BuildLine(strref line) } // Check for unterminated condition in source if (!contextStack.curr().next_source && - (!ConditionalAsm() || ConditionalConsumed() || conditional_depth)) { + (!ConditionalAsm() || ConditionalConsumed() || !conditional_depth)) { if (syntax == SYNTAX_MERLIN) { // this isn't a listed feature, conditional_nesting[0] = 0; // some files just seem to get away without closing conditional_consumed[0] = 0; conditional_depth = 0; } else { - PrintError(conditional_source[conditional_depth], error); + PrintError(conditional_source[conditional_depth], ERROR_UNTERMINATED_CONDITION); return ERROR_UNTERMINATED_CONDITION; } } @@ -6069,16 +6111,14 @@ void Asm::Assemble(strref source, strref filename, bool obj_target) SetCPU(cpu); StatusCode error = STATUS_OK; - contextStack.push(filename, source, source); + PushContext(filename, source, source); scope_address[scope_depth] = CurrSection().GetPC(); - while (contextStack.has_work()) { + while (contextStack.has_work() && error == STATUS_OK) { error = BuildSegment(); - if (contextStack.curr().complete()) { - if (contextStack.curr().scoped_context && scope_depth) - ExitScope(); - contextStack.pop(); - } else + if (contextStack.curr().complete()) + error = PopContext(); + else contextStack.curr().restart(); } if (error == STATUS_OK) { @@ -6108,7 +6148,9 @@ void Asm::Assemble(strref source, strref filename, bool obj_target) fwrite(errorText.get(), errorText.get_len(), 1, stderr); } } - } + } else + PrintError(&contextStack.curr() ? + contextStack.curr().read_source.get_line() : strref(), error); }