mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Group pointer and size as a ContentSpan struct
This commit is contained in:
@@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
#include "linkdefs.hpp"
|
#include "linkdefs.hpp"
|
||||||
|
|
||||||
|
#include "asm/lexer.hpp"
|
||||||
|
|
||||||
struct FileStackNode {
|
struct FileStackNode {
|
||||||
FileStackNodeType type;
|
FileStackNodeType type;
|
||||||
std::variant<
|
std::variant<
|
||||||
@@ -64,17 +66,14 @@ std::optional<std::string> fstk_FindFile(std::string const &path);
|
|||||||
bool yywrap();
|
bool yywrap();
|
||||||
void fstk_RunInclude(std::string const &path, bool updateStateNow);
|
void fstk_RunInclude(std::string const &path, bool updateStateNow);
|
||||||
void fstk_RunMacro(std::string const ¯oName, std::shared_ptr<MacroArgs> macroArgs);
|
void fstk_RunMacro(std::string const ¯oName, std::shared_ptr<MacroArgs> macroArgs);
|
||||||
void fstk_RunRept(
|
void fstk_RunRept(uint32_t count, int32_t reptLineNo, ContentSpan const &span);
|
||||||
uint32_t count, int32_t reptLineNo, std::shared_ptr<char const[]> body, size_t size
|
|
||||||
);
|
|
||||||
void fstk_RunFor(
|
void fstk_RunFor(
|
||||||
std::string const &symName,
|
std::string const &symName,
|
||||||
int32_t start,
|
int32_t start,
|
||||||
int32_t stop,
|
int32_t stop,
|
||||||
int32_t step,
|
int32_t step,
|
||||||
int32_t reptLineNo,
|
int32_t reptLineNo,
|
||||||
std::shared_ptr<char const[]> body,
|
ContentSpan const &span
|
||||||
size_t size
|
|
||||||
);
|
);
|
||||||
void fstk_StopRept();
|
void fstk_StopRept();
|
||||||
bool fstk_Break();
|
bool fstk_Break();
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ struct IfStackEntry {
|
|||||||
bool reachedElseBlock; // Whether an ELSE block ran already
|
bool reachedElseBlock; // Whether an ELSE block ran already
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ContentSpan {
|
||||||
|
std::shared_ptr<char[]> ptr;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
struct BufferedContent {
|
struct BufferedContent {
|
||||||
int fd;
|
int fd;
|
||||||
size_t index = 0; // Read index into the buffer
|
size_t index = 0; // Read index into the buffer
|
||||||
@@ -52,19 +57,17 @@ struct BufferedContent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct MmappedContent {
|
struct MmappedContent {
|
||||||
std::shared_ptr<char[]> ptr;
|
ContentSpan span;
|
||||||
size_t size;
|
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
|
|
||||||
MmappedContent(std::shared_ptr<char[]> ptr_, size_t size_) : ptr(ptr_), size(size_) {}
|
MmappedContent(std::shared_ptr<char[]> ptr, size_t size) : span({.ptr = ptr, .size = size}) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ViewedContent {
|
struct ViewedContent {
|
||||||
std::shared_ptr<char const[]> ptr;
|
ContentSpan span;
|
||||||
size_t size;
|
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
|
|
||||||
ViewedContent(std::shared_ptr<char const[]> ptr_, size_t size_) : ptr(ptr_), size(size_) {}
|
ViewedContent(ContentSpan const &span_) : span(span_) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LexerState {
|
struct LexerState {
|
||||||
@@ -95,9 +98,7 @@ struct LexerState {
|
|||||||
|
|
||||||
void setAsCurrentState();
|
void setAsCurrentState();
|
||||||
bool setFileAsNextState(std::string const &filePath, bool updateStateNow);
|
bool setFileAsNextState(std::string const &filePath, bool updateStateNow);
|
||||||
void setViewAsNextState(
|
void setViewAsNextState(char const *name, ContentSpan const &span, uint32_t lineNo_);
|
||||||
char const *name, std::shared_ptr<char const[]> ptr, size_t size, uint32_t lineNo_
|
|
||||||
);
|
|
||||||
|
|
||||||
void clear(uint32_t lineNo_);
|
void clear(uint32_t lineNo_);
|
||||||
};
|
};
|
||||||
@@ -137,8 +138,7 @@ void lexer_DumpStringExpansions();
|
|||||||
|
|
||||||
struct Capture {
|
struct Capture {
|
||||||
uint32_t lineNo;
|
uint32_t lineNo;
|
||||||
std::shared_ptr<char const[]> body;
|
ContentSpan span;
|
||||||
size_t size;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Capture lexer_CaptureRept();
|
Capture lexer_CaptureRept();
|
||||||
|
|||||||
@@ -10,9 +10,9 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <utility>
|
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
|
#include "asm/lexer.hpp"
|
||||||
#include "asm/section.hpp"
|
#include "asm/section.hpp"
|
||||||
|
|
||||||
enum SymbolType {
|
enum SymbolType {
|
||||||
@@ -39,7 +39,7 @@ struct Symbol {
|
|||||||
std::variant<
|
std::variant<
|
||||||
int32_t, // If isNumeric()
|
int32_t, // If isNumeric()
|
||||||
int32_t (*)(), // If isNumeric() and has a callback
|
int32_t (*)(), // If isNumeric() and has a callback
|
||||||
std::pair<std::shared_ptr<char const[]>, size_t>, // For SYM_MACRO
|
ContentSpan, // For SYM_MACRO
|
||||||
std::shared_ptr<std::string> // For SYM_EQUS
|
std::shared_ptr<std::string> // For SYM_EQUS
|
||||||
>
|
>
|
||||||
data;
|
data;
|
||||||
@@ -62,7 +62,7 @@ struct Symbol {
|
|||||||
|
|
||||||
int32_t getValue() const;
|
int32_t getValue() const;
|
||||||
int32_t getOutputValue() const;
|
int32_t getOutputValue() const;
|
||||||
std::pair<std::shared_ptr<char const[]>, size_t> getMacro() const;
|
ContentSpan const &getMacro() const;
|
||||||
std::shared_ptr<std::string> getEqus() const;
|
std::shared_ptr<std::string> getEqus() const;
|
||||||
uint32_t getConstantValue() const;
|
uint32_t getConstantValue() const;
|
||||||
};
|
};
|
||||||
@@ -89,9 +89,7 @@ Symbol *sym_FindScopedSymbol(std::string const &symName);
|
|||||||
// Find a scoped symbol by name; do not return `@` or `_NARG` when they have no value
|
// Find a scoped symbol by name; do not return `@` or `_NARG` when they have no value
|
||||||
Symbol *sym_FindScopedValidSymbol(std::string const &symName);
|
Symbol *sym_FindScopedValidSymbol(std::string const &symName);
|
||||||
Symbol const *sym_GetPC();
|
Symbol const *sym_GetPC();
|
||||||
Symbol *sym_AddMacro(
|
Symbol *sym_AddMacro(std::string const &symName, int32_t defLineNo, ContentSpan const &span);
|
||||||
std::string const &symName, int32_t defLineNo, std::shared_ptr<char const[]> body, size_t size
|
|
||||||
);
|
|
||||||
Symbol *sym_Ref(std::string const &symName);
|
Symbol *sym_Ref(std::string const &symName);
|
||||||
Symbol *sym_AddString(std::string const &symName, std::shared_ptr<std::string> value);
|
Symbol *sym_AddString(std::string const &symName, std::shared_ptr<std::string> value);
|
||||||
Symbol *sym_RedefString(std::string const &symName, std::shared_ptr<std::string> value);
|
Symbol *sym_RedefString(std::string const &symName, std::shared_ptr<std::string> value);
|
||||||
|
|||||||
@@ -281,13 +281,10 @@ static void newMacroContext(Symbol const ¯o, std::shared_ptr<MacroArgs> macr
|
|||||||
.macroArgs = macroArgs,
|
.macroArgs = macroArgs,
|
||||||
});
|
});
|
||||||
|
|
||||||
auto [body, size] = macro.getMacro();
|
context.lexerState.setViewAsNextState("MACRO", macro.getMacro(), macro.fileLine);
|
||||||
context.lexerState.setViewAsNextState("MACRO", body, size, macro.fileLine);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Context &newReptContext(
|
static Context &newReptContext(int32_t reptLineNo, ContentSpan const &span, uint32_t count) {
|
||||||
int32_t reptLineNo, std::shared_ptr<char const[]> body, size_t size, uint32_t count
|
|
||||||
) {
|
|
||||||
checkRecursionDepth();
|
checkRecursionDepth();
|
||||||
|
|
||||||
Context &oldContext = contextStack.top();
|
Context &oldContext = contextStack.top();
|
||||||
@@ -309,7 +306,7 @@ static Context &newReptContext(
|
|||||||
.macroArgs = oldContext.macroArgs,
|
.macroArgs = oldContext.macroArgs,
|
||||||
});
|
});
|
||||||
|
|
||||||
context.lexerState.setViewAsNextState("REPT", body, size, reptLineNo);
|
context.lexerState.setViewAsNextState("REPT", span, reptLineNo);
|
||||||
|
|
||||||
context.nbReptIters = count;
|
context.nbReptIters = count;
|
||||||
|
|
||||||
@@ -349,13 +346,11 @@ void fstk_RunMacro(std::string const ¯oName, std::shared_ptr<MacroArgs> macr
|
|||||||
newMacroContext(*macro, macroArgs);
|
newMacroContext(*macro, macroArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fstk_RunRept(
|
void fstk_RunRept(uint32_t count, int32_t reptLineNo, ContentSpan const &span) {
|
||||||
uint32_t count, int32_t reptLineNo, std::shared_ptr<char const[]> body, size_t size
|
|
||||||
) {
|
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
newReptContext(reptLineNo, body, size, count);
|
newReptContext(reptLineNo, span, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fstk_RunFor(
|
void fstk_RunFor(
|
||||||
@@ -364,8 +359,7 @@ void fstk_RunFor(
|
|||||||
int32_t stop,
|
int32_t stop,
|
||||||
int32_t step,
|
int32_t step,
|
||||||
int32_t reptLineNo,
|
int32_t reptLineNo,
|
||||||
std::shared_ptr<char const[]> body,
|
ContentSpan const &span
|
||||||
size_t size
|
|
||||||
) {
|
) {
|
||||||
if (Symbol *sym = sym_AddVar(symName, start); sym->type != SYM_VAR)
|
if (Symbol *sym = sym_AddVar(symName, start); sym->type != SYM_VAR)
|
||||||
return;
|
return;
|
||||||
@@ -386,7 +380,7 @@ void fstk_RunFor(
|
|||||||
if (count == 0)
|
if (count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Context &context = newReptContext(reptLineNo, body, size, count);
|
Context &context = newReptContext(reptLineNo, span, count);
|
||||||
context.isForLoop = true;
|
context.isForLoop = true;
|
||||||
context.forValue = start;
|
context.forValue = start;
|
||||||
context.forStep = step;
|
context.forStep = step;
|
||||||
|
|||||||
@@ -460,11 +460,9 @@ bool LexerState::setFileAsNextState(std::string const &filePath, bool updateStat
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LexerState::setViewAsNextState(
|
void LexerState::setViewAsNextState(char const *name, ContentSpan const &span, uint32_t lineNo_) {
|
||||||
char const *name, std::shared_ptr<char const[]> ptr, size_t size, uint32_t lineNo_
|
|
||||||
) {
|
|
||||||
path = name; // Used to report read errors in `peekInternal`
|
path = name; // Used to report read errors in `peekInternal`
|
||||||
content.emplace<ViewedContent>(ptr, size);
|
content.emplace<ViewedContent>(span);
|
||||||
clear(lineNo_);
|
clear(lineNo_);
|
||||||
lexerStateEOL = this;
|
lexerStateEOL = this;
|
||||||
}
|
}
|
||||||
@@ -675,12 +673,12 @@ static int peekInternal(uint8_t distance) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (auto *mmap = std::get_if<MmappedContent>(&lexerState->content); mmap) {
|
if (auto *mmap = std::get_if<MmappedContent>(&lexerState->content); mmap) {
|
||||||
if (size_t idx = mmap->offset + distance; idx < mmap->size)
|
if (size_t idx = mmap->offset + distance; idx < mmap->span.size)
|
||||||
return (uint8_t)mmap->ptr[idx];
|
return (uint8_t)mmap->span.ptr[idx];
|
||||||
return EOF;
|
return EOF;
|
||||||
} else if (auto *view = std::get_if<ViewedContent>(&lexerState->content); view) {
|
} else if (auto *view = std::get_if<ViewedContent>(&lexerState->content); view) {
|
||||||
if (size_t idx = view->offset + distance; idx < view->size)
|
if (size_t idx = view->offset + distance; idx < view->span.size)
|
||||||
return (uint8_t)view->ptr[idx];
|
return (uint8_t)view->span.ptr[idx];
|
||||||
return EOF;
|
return EOF;
|
||||||
} else {
|
} else {
|
||||||
assert(std::holds_alternative<BufferedContent>(lexerState->content));
|
assert(std::holds_alternative<BufferedContent>(lexerState->content));
|
||||||
@@ -2180,28 +2178,28 @@ static Capture startCapture() {
|
|||||||
lexerState->capturing = true;
|
lexerState->capturing = true;
|
||||||
lexerState->captureSize = 0;
|
lexerState->captureSize = 0;
|
||||||
|
|
||||||
Capture capture = {.lineNo = lexer_GetLineNo(), .body = nullptr, .size = 0};
|
uint32_t lineNo = lexer_GetLineNo();
|
||||||
if (auto *mmap = std::get_if<MmappedContent>(&lexerState->content);
|
if (auto *mmap = std::get_if<MmappedContent>(&lexerState->content);
|
||||||
mmap && lexerState->expansions.empty()) {
|
mmap && lexerState->expansions.empty()) {
|
||||||
capture.body = std::shared_ptr<char const[]>(mmap->ptr, &mmap->ptr[mmap->offset]);
|
return {.lineNo = lineNo, .span = {.ptr = std::shared_ptr<char[]>(mmap->span.ptr, &mmap->span.ptr[mmap->offset]), .size = 0}};
|
||||||
} else if (auto *view = std::get_if<ViewedContent>(&lexerState->content);
|
} else if (auto *view = std::get_if<ViewedContent>(&lexerState->content);
|
||||||
view && lexerState->expansions.empty()) {
|
view && lexerState->expansions.empty()) {
|
||||||
capture.body = std::shared_ptr<char const[]>(view->ptr, &view->ptr[view->offset]);
|
return {.lineNo = lineNo, .span = {.ptr = std::shared_ptr<char[]>(view->span.ptr, &view->span.ptr[view->offset]), .size = 0}};
|
||||||
} else {
|
} else {
|
||||||
// `capture.body == nullptr`; indicates to retrieve the capture buffer when done capturing
|
|
||||||
assert(lexerState->captureBuf == nullptr);
|
assert(lexerState->captureBuf == nullptr);
|
||||||
lexerState->captureBuf = std::make_shared<std::vector<char>>();
|
lexerState->captureBuf = std::make_shared<std::vector<char>>();
|
||||||
|
// `.span.ptr == nullptr`; indicates to retrieve the capture buffer when done capturing
|
||||||
|
return {.lineNo = lineNo, .span = {.ptr = nullptr, .size = 0}};
|
||||||
}
|
}
|
||||||
return capture;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void endCapture(Capture &capture) {
|
static void endCapture(Capture &capture) {
|
||||||
// This being `nullptr` means we're capturing from the capture buffer, which is reallocated
|
// This being `nullptr` means we're capturing from the capture buffer, which is reallocated
|
||||||
// during the whole capture process, and so MUST be retrieved at the end
|
// during the whole capture process, and so MUST be retrieved at the end
|
||||||
if (!capture.body)
|
if (!capture.span.ptr)
|
||||||
capture.body =
|
capture.span.ptr =
|
||||||
std::shared_ptr<char const[]>(lexerState->captureBuf, lexerState->captureBuf->data());
|
std::shared_ptr<char[]>(lexerState->captureBuf, lexerState->captureBuf->data());
|
||||||
capture.size = lexerState->captureSize;
|
capture.span.size = lexerState->captureSize;
|
||||||
|
|
||||||
// ENDR/ENDM or EOF puts us past the start of the line
|
// ENDR/ENDM or EOF puts us past the start of the line
|
||||||
lexerState->atLineStart = false;
|
lexerState->atLineStart = false;
|
||||||
@@ -2238,7 +2236,7 @@ Capture lexer_CaptureRept() {
|
|||||||
endCapture(capture);
|
endCapture(capture);
|
||||||
// The final ENDR has been captured, but we don't want it!
|
// The final ENDR has been captured, but we don't want it!
|
||||||
// We know we have read exactly "ENDR", not e.g. an EQUS
|
// We know we have read exactly "ENDR", not e.g. an EQUS
|
||||||
capture.size -= strlen("ENDR");
|
capture.span.size -= strlen("ENDR");
|
||||||
return capture;
|
return capture;
|
||||||
}
|
}
|
||||||
depth--;
|
depth--;
|
||||||
@@ -2254,7 +2252,7 @@ Capture lexer_CaptureRept() {
|
|||||||
if (c == EOF) {
|
if (c == EOF) {
|
||||||
error("Unterminated REPT/FOR block\n");
|
error("Unterminated REPT/FOR block\n");
|
||||||
endCapture(capture);
|
endCapture(capture);
|
||||||
capture.body = nullptr; // Indicates that it reached EOF before an ENDR
|
capture.span.ptr = nullptr; // Indicates that it reached EOF before an ENDR
|
||||||
return capture;
|
return capture;
|
||||||
} else if (c == '\n' || c == '\r') {
|
} else if (c == '\n' || c == '\r') {
|
||||||
handleCRLF(c);
|
handleCRLF(c);
|
||||||
@@ -2284,7 +2282,7 @@ Capture lexer_CaptureMacro() {
|
|||||||
endCapture(capture);
|
endCapture(capture);
|
||||||
// The ENDM has been captured, but we don't want it!
|
// The ENDM has been captured, but we don't want it!
|
||||||
// We know we have read exactly "ENDM", not e.g. an EQUS
|
// We know we have read exactly "ENDM", not e.g. an EQUS
|
||||||
capture.size -= strlen("ENDM");
|
capture.span.size -= strlen("ENDM");
|
||||||
return capture;
|
return capture;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -2297,7 +2295,7 @@ Capture lexer_CaptureMacro() {
|
|||||||
if (c == EOF) {
|
if (c == EOF) {
|
||||||
error("Unterminated macro definition\n");
|
error("Unterminated macro definition\n");
|
||||||
endCapture(capture);
|
endCapture(capture);
|
||||||
capture.body = nullptr; // Indicates that it reached EOF before an ENDM
|
capture.span.ptr = nullptr; // Indicates that it reached EOF before an ENDM
|
||||||
return capture;
|
return capture;
|
||||||
} else if (c == '\n' || c == '\r') {
|
} else if (c == '\n' || c == '\r') {
|
||||||
handleCRLF(c);
|
handleCRLF(c);
|
||||||
|
|||||||
@@ -866,8 +866,8 @@ load:
|
|||||||
|
|
||||||
rept:
|
rept:
|
||||||
POP_REPT uconst NEWLINE capture_rept endofline {
|
POP_REPT uconst NEWLINE capture_rept endofline {
|
||||||
if ($4.body)
|
if ($4.span.ptr)
|
||||||
fstk_RunRept($2, $4.lineNo, $4.body, $4.size);
|
fstk_RunRept($2, $4.lineNo, $4.span);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -877,8 +877,8 @@ for:
|
|||||||
} ID {
|
} ID {
|
||||||
lexer_ToggleStringExpansion(true);
|
lexer_ToggleStringExpansion(true);
|
||||||
} COMMA for_args NEWLINE capture_rept endofline {
|
} COMMA for_args NEWLINE capture_rept endofline {
|
||||||
if ($8.body)
|
if ($8.span.ptr)
|
||||||
fstk_RunFor($3, $6.start, $6.stop, $6.step, $8.lineNo, $8.body, $8.size);
|
fstk_RunFor($3, $6.start, $6.stop, $6.step, $8.lineNo, $8.span);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -919,8 +919,8 @@ def_macro:
|
|||||||
} ID {
|
} ID {
|
||||||
lexer_ToggleStringExpansion(true);
|
lexer_ToggleStringExpansion(true);
|
||||||
} NEWLINE capture_macro endofline {
|
} NEWLINE capture_macro endofline {
|
||||||
if ($6.body)
|
if ($6.span.ptr)
|
||||||
sym_AddMacro($3, $6.lineNo, $6.body, $6.size);
|
sym_AddMacro($3, $6.lineNo, $6.span);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -74,9 +74,9 @@ int32_t Symbol::getOutputValue() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<std::shared_ptr<char const []>, size_t> Symbol::getMacro() const {
|
ContentSpan const &Symbol::getMacro() const {
|
||||||
assert((std::holds_alternative<std::pair<std::shared_ptr<char const[]>, size_t>>(data)));
|
assert((std::holds_alternative<ContentSpan>(data)));
|
||||||
return std::get<std::pair<std::shared_ptr<char const[]>, size_t>>(data);
|
return std::get<ContentSpan>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<std::string> Symbol::getEqus() const {
|
std::shared_ptr<std::string> Symbol::getEqus() const {
|
||||||
@@ -489,16 +489,14 @@ void sym_Export(std::string const &symName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add a macro definition
|
// Add a macro definition
|
||||||
Symbol *sym_AddMacro(
|
Symbol *sym_AddMacro(std::string const &symName, int32_t defLineNo, ContentSpan const &span) {
|
||||||
std::string const &symName, int32_t defLineNo, std::shared_ptr<char const[]> body, size_t size
|
|
||||||
) {
|
|
||||||
Symbol *sym = createNonrelocSymbol(symName, false);
|
Symbol *sym = createNonrelocSymbol(symName, false);
|
||||||
|
|
||||||
if (!sym)
|
if (!sym)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
sym->type = SYM_MACRO;
|
sym->type = SYM_MACRO;
|
||||||
sym->data = std::make_pair(body, size);
|
sym->data = span;
|
||||||
|
|
||||||
sym->src = fstk_GetFileStack();
|
sym->src = fstk_GetFileStack();
|
||||||
// The symbol is created at the line after the `ENDM`,
|
// The symbol is created at the line after the `ENDM`,
|
||||||
|
|||||||
Reference in New Issue
Block a user