mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Use std::shared_ptr for lexer capture buffers
This commit is contained in:
@@ -64,14 +64,16 @@ 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(uint32_t count, int32_t reptLineNo, char const *body, size_t size);
|
void fstk_RunRept(
|
||||||
|
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,
|
||||||
char const *body,
|
std::shared_ptr<char const[]> body,
|
||||||
size_t size
|
size_t size
|
||||||
);
|
);
|
||||||
void fstk_StopRept();
|
void fstk_StopRept();
|
||||||
|
|||||||
@@ -52,21 +52,19 @@ struct BufferedContent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct MmappedContent {
|
struct MmappedContent {
|
||||||
char *ptr;
|
std::shared_ptr<char[]> ptr;
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
bool isReferenced = false; // If a macro in this file requires not unmapping it
|
|
||||||
|
|
||||||
MmappedContent(char *ptr_, size_t size_) : ptr(ptr_), size(size_) {}
|
MmappedContent(std::shared_ptr<char[]> ptr_, size_t size_) : ptr(ptr_), size(size_) {}
|
||||||
~MmappedContent();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ViewedContent {
|
struct ViewedContent {
|
||||||
char const *ptr;
|
std::shared_ptr<char const[]> ptr;
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
|
|
||||||
ViewedContent(char const *ptr_, size_t size_) : ptr(ptr_), size(size_) {}
|
ViewedContent(std::shared_ptr<char const[]> ptr_, size_t size_) : ptr(ptr_), size(size_) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LexerState {
|
struct LexerState {
|
||||||
@@ -82,7 +80,8 @@ struct LexerState {
|
|||||||
|
|
||||||
bool capturing; // Whether the text being lexed should be captured
|
bool capturing; // Whether the text being lexed should be captured
|
||||||
size_t captureSize; // Amount of text captured
|
size_t captureSize; // Amount of text captured
|
||||||
std::vector<char> *captureBuf; // Buffer to send the captured text to if non-null
|
std::shared_ptr<std::vector<char>>
|
||||||
|
captureBuf; // Buffer to send the captured text to if non-null
|
||||||
|
|
||||||
bool disableMacroArgs;
|
bool disableMacroArgs;
|
||||||
bool disableInterpolation;
|
bool disableInterpolation;
|
||||||
@@ -96,7 +95,9 @@ struct LexerState {
|
|||||||
|
|
||||||
void setAsCurrentState();
|
void setAsCurrentState();
|
||||||
bool setFileAsNextState(std::string const &filePath, bool updateStateNow);
|
bool setFileAsNextState(std::string const &filePath, bool updateStateNow);
|
||||||
void setViewAsNextState(char const *name, char const *buf, size_t size, uint32_t lineNo_);
|
void setViewAsNextState(
|
||||||
|
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_);
|
||||||
};
|
};
|
||||||
@@ -136,7 +137,7 @@ void lexer_DumpStringExpansions();
|
|||||||
|
|
||||||
struct Capture {
|
struct Capture {
|
||||||
uint32_t lineNo;
|
uint32_t lineNo;
|
||||||
char const *body;
|
std::shared_ptr<char const[]> body;
|
||||||
size_t size;
|
size_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <utility>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
#include "asm/section.hpp"
|
#include "asm/section.hpp"
|
||||||
@@ -38,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::string_view, // For SYM_MACRO
|
std::pair<std::shared_ptr<char const[]>, size_t>, // For SYM_MACRO
|
||||||
std::shared_ptr<std::string> // For SYM_EQUS
|
std::shared_ptr<std::string> // For SYM_EQUS
|
||||||
>
|
>
|
||||||
data;
|
data;
|
||||||
@@ -61,7 +62,7 @@ struct Symbol {
|
|||||||
|
|
||||||
int32_t getValue() const;
|
int32_t getValue() const;
|
||||||
int32_t getOutputValue() const;
|
int32_t getOutputValue() const;
|
||||||
std::string_view getMacro() const;
|
std::pair<std::shared_ptr<char const[]>, size_t> getMacro() const;
|
||||||
std::shared_ptr<std::string> getEqus() const;
|
std::shared_ptr<std::string> getEqus() const;
|
||||||
uint32_t getConstantValue() const;
|
uint32_t getConstantValue() const;
|
||||||
};
|
};
|
||||||
@@ -88,7 +89,9 @@ 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(std::string const &symName, int32_t defLineNo, char const *body, size_t size);
|
Symbol *sym_AddMacro(
|
||||||
|
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,11 +281,13 @@ static void newMacroContext(Symbol const ¯o, std::shared_ptr<MacroArgs> macr
|
|||||||
.macroArgs = macroArgs,
|
.macroArgs = macroArgs,
|
||||||
});
|
});
|
||||||
|
|
||||||
std::string_view view = macro.getMacro();
|
auto [body, size] = macro.getMacro();
|
||||||
context.lexerState.setViewAsNextState("MACRO", view.data(), view.size(), macro.fileLine);
|
context.lexerState.setViewAsNextState("MACRO", body, size, macro.fileLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Context &newReptContext(int32_t reptLineNo, char const *body, size_t size, uint32_t count) {
|
static Context &newReptContext(
|
||||||
|
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();
|
||||||
@@ -347,7 +349,9 @@ void fstk_RunMacro(std::string const ¯oName, std::shared_ptr<MacroArgs> macr
|
|||||||
newMacroContext(*macro, macroArgs);
|
newMacroContext(*macro, macroArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fstk_RunRept(uint32_t count, int32_t reptLineNo, char const *body, size_t size) {
|
void fstk_RunRept(
|
||||||
|
uint32_t count, int32_t reptLineNo, std::shared_ptr<char const[]> body, size_t size
|
||||||
|
) {
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -360,7 +364,7 @@ void fstk_RunFor(
|
|||||||
int32_t stop,
|
int32_t stop,
|
||||||
int32_t step,
|
int32_t step,
|
||||||
int32_t reptLineNo,
|
int32_t reptLineNo,
|
||||||
char const *body,
|
std::shared_ptr<char const[]> body,
|
||||||
size_t size
|
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)
|
||||||
|
|||||||
@@ -69,9 +69,11 @@ static void mapFile(void *&mappingAddr, int fd, std::string const &path, size_t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int munmap(void *mappingAddr, size_t) {
|
struct MunmapDeleter {
|
||||||
return UnmapViewOfFile(mappingAddr) == 0 ? -1 : 0;
|
MunmapDeleter(size_t) {}
|
||||||
}
|
|
||||||
|
void operator()(char *mappingAddr) { UnmapViewOfFile(mappingAddr); }
|
||||||
|
};
|
||||||
|
|
||||||
#else // defined(_MSC_VER) || defined(__MINGW32__)
|
#else // defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
@@ -88,6 +90,14 @@ static void mapFile(void *&mappingAddr, int fd, std::string const &path, size_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MunmapDeleter {
|
||||||
|
size_t mappingSize;
|
||||||
|
|
||||||
|
MunmapDeleter(size_t mappingSize_) : mappingSize(mappingSize_) {}
|
||||||
|
|
||||||
|
void operator()(char *mappingAddr) { munmap(mappingAddr, mappingSize); }
|
||||||
|
};
|
||||||
|
|
||||||
#endif // !( defined(_MSC_VER) || defined(__MINGW32__) )
|
#endif // !( defined(_MSC_VER) || defined(__MINGW32__) )
|
||||||
|
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
@@ -415,7 +425,12 @@ bool LexerState::setFileAsNextState(std::string const &filePath, bool updateStat
|
|||||||
|
|
||||||
if (mappingAddr != MAP_FAILED) {
|
if (mappingAddr != MAP_FAILED) {
|
||||||
close(fd);
|
close(fd);
|
||||||
content.emplace<MmappedContent>((char *)mappingAddr, (size_t)statBuf.st_size);
|
content.emplace<MmappedContent>(
|
||||||
|
std::shared_ptr<char[]>(
|
||||||
|
(char *)mappingAddr, MunmapDeleter((size_t)statBuf.st_size)
|
||||||
|
),
|
||||||
|
(size_t)statBuf.st_size
|
||||||
|
);
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf("File \"%s\" is mmap()ped\n", path.c_str());
|
printf("File \"%s\" is mmap()ped\n", path.c_str());
|
||||||
isMmapped = true;
|
isMmapped = true;
|
||||||
@@ -446,10 +461,10 @@ bool LexerState::setFileAsNextState(std::string const &filePath, bool updateStat
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LexerState::setViewAsNextState(
|
void LexerState::setViewAsNextState(
|
||||||
char const *name, char const *buf, size_t size, 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>(buf, size);
|
content.emplace<ViewedContent>(ptr, size);
|
||||||
clear(lineNo_);
|
clear(lineNo_);
|
||||||
lexerStateEOL = this;
|
lexerStateEOL = this;
|
||||||
}
|
}
|
||||||
@@ -482,12 +497,6 @@ BufferedContent::~BufferedContent() {
|
|||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
MmappedContent::~MmappedContent() {
|
|
||||||
// FIXME: This never unmaps a referenced file!
|
|
||||||
if (!isReferenced)
|
|
||||||
munmap(ptr, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void lexer_SetMode(LexerMode mode) {
|
void lexer_SetMode(LexerMode mode) {
|
||||||
lexerState->mode = mode;
|
lexerState->mode = mode;
|
||||||
}
|
}
|
||||||
@@ -2174,17 +2183,14 @@ static Capture startCapture() {
|
|||||||
Capture capture = {.lineNo = lexer_GetLineNo(), .body = nullptr, .size = 0};
|
Capture capture = {.lineNo = lexer_GetLineNo(), .body = nullptr, .size = 0};
|
||||||
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 = &mmap->ptr[mmap->offset];
|
capture.body = std::shared_ptr<char const[]>(mmap->ptr, &mmap->ptr[mmap->offset]);
|
||||||
} 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 = &view->ptr[view->offset];
|
capture.body = std::shared_ptr<char const[]>(view->ptr, &view->ptr[view->offset]);
|
||||||
} else {
|
} else {
|
||||||
// `capture.body == nullptr`; indicates to retrieve the capture buffer when done capturing
|
// `capture.body == nullptr`; indicates to retrieve the capture buffer when done capturing
|
||||||
assert(lexerState->captureBuf == nullptr);
|
assert(lexerState->captureBuf == nullptr);
|
||||||
// FIXME: This leaks the captured text!
|
lexerState->captureBuf = std::make_shared<std::vector<char>>();
|
||||||
lexerState->captureBuf = new (std::nothrow) std::vector<char>();
|
|
||||||
if (!lexerState->captureBuf)
|
|
||||||
fatalerror("Failed to allocate capture buffer: %s\n", strerror(errno));
|
|
||||||
}
|
}
|
||||||
return capture;
|
return capture;
|
||||||
}
|
}
|
||||||
@@ -2193,7 +2199,8 @@ 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.body)
|
||||||
capture.body = lexerState->captureBuf->data();
|
capture.body =
|
||||||
|
std::shared_ptr<char const[]>(lexerState->captureBuf, lexerState->captureBuf->data());
|
||||||
capture.size = lexerState->captureSize;
|
capture.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
|
||||||
@@ -2262,10 +2269,6 @@ Capture lexer_CaptureMacro() {
|
|||||||
|
|
||||||
Defer reenableExpansions = scopedDisableExpansions();
|
Defer reenableExpansions = scopedDisableExpansions();
|
||||||
|
|
||||||
// If the file is `mmap`ed, we need not to unmap it to keep access to the macro
|
|
||||||
if (auto *mmap = std::get_if<MmappedContent>(&lexerState->content); mmap)
|
|
||||||
mmap->isReferenced = true;
|
|
||||||
|
|
||||||
int c = EOF;
|
int c = EOF;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|||||||
@@ -74,9 +74,9 @@ int32_t Symbol::getOutputValue() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view Symbol::getMacro() const {
|
std::pair<std::shared_ptr<char const []>, size_t> Symbol::getMacro() const {
|
||||||
assert(std::holds_alternative<std::string_view>(data));
|
assert((std::holds_alternative<std::pair<std::shared_ptr<char const[]>, size_t>>(data)));
|
||||||
return std::get<std::string_view>(data);
|
return std::get<std::pair<std::shared_ptr<char const[]>, size_t>>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<std::string> Symbol::getEqus() const {
|
std::shared_ptr<std::string> Symbol::getEqus() const {
|
||||||
@@ -489,14 +489,16 @@ void sym_Export(std::string const &symName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add a macro definition
|
// Add a macro definition
|
||||||
Symbol *sym_AddMacro(std::string const &symName, int32_t defLineNo, char const *body, size_t size) {
|
Symbol *sym_AddMacro(
|
||||||
|
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::string_view(body, size);
|
sym->data = std::make_pair(body, size);
|
||||||
|
|
||||||
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