Use std::shared_ptr for lexer capture buffers

This commit is contained in:
Rangi42
2024-03-26 13:45:20 -04:00
committed by Sylvie
parent a68bebf4a2
commit bf0cabb3ea
6 changed files with 67 additions and 52 deletions

View File

@@ -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 &macroName, std::shared_ptr<MacroArgs> macroArgs); void fstk_RunMacro(std::string const &macroName, 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();

View File

@@ -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 {
@@ -80,9 +78,10 @@ struct LexerState {
std::deque<IfStackEntry> ifStack; std::deque<IfStackEntry> ifStack;
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;
}; };

View File

@@ -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"
@@ -36,10 +37,10 @@ struct Symbol {
uint32_t fileLine; // Line where the symbol was defined uint32_t fileLine; // Line where the symbol was defined
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);

View File

@@ -281,11 +281,13 @@ static void newMacroContext(Symbol const &macro, 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 &macroName, 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)

View File

@@ -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 (;;) {

View File

@@ -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`,