diff --git a/source/app.d b/source/app.d index c195842..053f713 100644 --- a/source/app.d +++ b/source/app.d @@ -18,6 +18,7 @@ import std.algorithm; import std.array; +import std.ascii; import std.conv; import std.file; import std.math; @@ -85,6 +86,7 @@ class Label { Label[string] labelTable; Label currentLabel; +string lastGlobalLabel; alias int function(int a, int b) OperatorFunction; @@ -261,21 +263,23 @@ void readSpaces() { } string readLabel() { - string label; + int firstColumn = column; while (!eol()) { char c = line[column++]; - if (c >= '0' && c <= '9' || c == '_') { - label ~= c; + if (c >= '0' && c <= '9' || c == '_' || c == '?') continue; - } c &= 0xdf; - if (c >= 'A' && c <= 'Z') { - label ~= c; + if (c >= 'A' && c <= 'Z') continue; - } column--; break; } + string label = line[firstColumn .. column].toUpper; + if (label.startsWith('?')) { + if (lastGlobalLabel is null) + throw new AssemblyError("Global label must be declared first"); + label = lastGlobalLabel ~ label; + } return label >= "A" ? label : null; } @@ -2688,6 +2692,8 @@ void assemblyLine() { currentLabel = null; if (label !is null) { if (!inFalseCondition()) { + if (!label.canFind('?')) + lastGlobalLabel = label; if (!pass2) { if (label in labelTable) throw new AssemblyError("Label declared twice"); diff --git a/xasm.1.asciidoc b/xasm.1.asciidoc index 39d262d..4a0f7d4 100644 --- a/xasm.1.asciidoc +++ b/xasm.1.asciidoc @@ -95,6 +95,28 @@ The label will be assigned the current value of the 'origin counter' unless you use it with the `EQU` directive where it is assigned the value of the `EQU` argument. +Any label name starting with `?` (question mark) refers to a 'local label'. +It is implicitly prefixed with the name of the most recently defined +'global label' (i.e. a label without any `?` in name), +and stays visible until another global label is defined. +It is still possible to access a local label from anywhere in the source +by specifying its full name. +Local labels provide a way to reuse common, short label names while keeping +them unique. +Example: +---- +foo ldy #0 +?loop lda data,y ; full label name is FOO?LOOP + beq ?ret + jsr sendByte + iny:bne ?loop +?ret rts + +bar lda baz + beq foo?ret ; ok + bne ?loop ; ERROR: Undeclared label: BAR?LOOP +---- + Instructions and directives must be preceded with some whitespace. Without leading whitespace they are treated as label names. For example: