diff --git a/include/asm/fstack.hpp b/include/asm/fstack.hpp index 62b54860..283f5513 100644 --- a/include/asm/fstack.hpp +++ b/include/asm/fstack.hpp @@ -64,14 +64,16 @@ std::optional fstk_FindFile(std::string const &path); bool yywrap(); void fstk_RunInclude(std::string const &path, bool updateStateNow); void fstk_RunMacro(std::string const ¯oName, std::shared_ptr 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 body, size_t size +); void fstk_RunFor( std::string const &symName, int32_t start, int32_t stop, int32_t step, int32_t reptLineNo, - char const *body, + std::shared_ptr body, size_t size ); void fstk_StopRept(); diff --git a/include/asm/lexer.hpp b/include/asm/lexer.hpp index 10fde61d..c786e566 100644 --- a/include/asm/lexer.hpp +++ b/include/asm/lexer.hpp @@ -52,21 +52,19 @@ struct BufferedContent { }; struct MmappedContent { - char *ptr; + std::shared_ptr ptr; size_t size; 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(); + MmappedContent(std::shared_ptr ptr_, size_t size_) : ptr(ptr_), size(size_) {} }; struct ViewedContent { - char const *ptr; + std::shared_ptr ptr; size_t size; size_t offset = 0; - ViewedContent(char const *ptr_, size_t size_) : ptr(ptr_), size(size_) {} + ViewedContent(std::shared_ptr ptr_, size_t size_) : ptr(ptr_), size(size_) {} }; struct LexerState { @@ -80,9 +78,10 @@ struct LexerState { std::deque ifStack; - bool capturing; // Whether the text being lexed should be captured - size_t captureSize; // Amount of text captured - std::vector *captureBuf; // Buffer to send the captured text to if non-null + bool capturing; // Whether the text being lexed should be captured + size_t captureSize; // Amount of text captured + std::shared_ptr> + captureBuf; // Buffer to send the captured text to if non-null bool disableMacroArgs; bool disableInterpolation; @@ -96,7 +95,9 @@ struct LexerState { void setAsCurrentState(); 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 ptr, size_t size, uint32_t lineNo_ + ); void clear(uint32_t lineNo_); }; @@ -136,7 +137,7 @@ void lexer_DumpStringExpansions(); struct Capture { uint32_t lineNo; - char const *body; + std::shared_ptr body; size_t size; }; diff --git a/include/asm/symbol.hpp b/include/asm/symbol.hpp index 1adf46e9..ab5ed9de 100644 --- a/include/asm/symbol.hpp +++ b/include/asm/symbol.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "asm/section.hpp" @@ -36,10 +37,10 @@ struct Symbol { uint32_t fileLine; // Line where the symbol was defined std::variant< - int32_t, // If isNumeric() - int32_t (*)(), // If isNumeric() and has a callback - std::string_view, // For SYM_MACRO - std::shared_ptr // For SYM_EQUS + int32_t, // If isNumeric() + int32_t (*)(), // If isNumeric() and has a callback + std::pair, size_t>, // For SYM_MACRO + std::shared_ptr // For SYM_EQUS > data; @@ -61,7 +62,7 @@ struct Symbol { int32_t getValue() const; int32_t getOutputValue() const; - std::string_view getMacro() const; + std::pair, size_t> getMacro() const; std::shared_ptr getEqus() 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 Symbol *sym_FindScopedValidSymbol(std::string const &symName); 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 body, size_t size +); Symbol *sym_Ref(std::string const &symName); Symbol *sym_AddString(std::string const &symName, std::shared_ptr value); Symbol *sym_RedefString(std::string const &symName, std::shared_ptr value); diff --git a/src/asm/fstack.cpp b/src/asm/fstack.cpp index 3cc0506c..8043f4fb 100644 --- a/src/asm/fstack.cpp +++ b/src/asm/fstack.cpp @@ -281,11 +281,13 @@ static void newMacroContext(Symbol const ¯o, std::shared_ptr macr .macroArgs = macroArgs, }); - std::string_view view = macro.getMacro(); - context.lexerState.setViewAsNextState("MACRO", view.data(), view.size(), macro.fileLine); + auto [body, size] = macro.getMacro(); + 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 body, size_t size, uint32_t count +) { checkRecursionDepth(); Context &oldContext = contextStack.top(); @@ -347,7 +349,9 @@ void fstk_RunMacro(std::string const ¯oName, std::shared_ptr macr 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 body, size_t size +) { if (count == 0) return; @@ -360,7 +364,7 @@ void fstk_RunFor( int32_t stop, int32_t step, int32_t reptLineNo, - char const *body, + std::shared_ptr body, size_t size ) { if (Symbol *sym = sym_AddVar(symName, start); sym->type != SYM_VAR) diff --git a/src/asm/lexer.cpp b/src/asm/lexer.cpp index a45d1db4..a4ffbf62 100644 --- a/src/asm/lexer.cpp +++ b/src/asm/lexer.cpp @@ -69,9 +69,11 @@ static void mapFile(void *&mappingAddr, int fd, std::string const &path, size_t) } } -static int munmap(void *mappingAddr, size_t) { - return UnmapViewOfFile(mappingAddr) == 0 ? -1 : 0; -} +struct MunmapDeleter { + MunmapDeleter(size_t) {} + + void operator()(char *mappingAddr) { UnmapViewOfFile(mappingAddr); } +}; #else // defined(_MSC_VER) || defined(__MINGW32__) #include @@ -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__) ) using namespace std::literals; @@ -415,7 +425,12 @@ bool LexerState::setFileAsNextState(std::string const &filePath, bool updateStat if (mappingAddr != MAP_FAILED) { close(fd); - content.emplace((char *)mappingAddr, (size_t)statBuf.st_size); + content.emplace( + std::shared_ptr( + (char *)mappingAddr, MunmapDeleter((size_t)statBuf.st_size) + ), + (size_t)statBuf.st_size + ); if (verbose) printf("File \"%s\" is mmap()ped\n", path.c_str()); isMmapped = true; @@ -446,10 +461,10 @@ bool LexerState::setFileAsNextState(std::string const &filePath, bool updateStat } void LexerState::setViewAsNextState( - char const *name, char const *buf, size_t size, uint32_t lineNo_ + char const *name, std::shared_ptr ptr, size_t size, uint32_t lineNo_ ) { path = name; // Used to report read errors in `peekInternal` - content.emplace(buf, size); + content.emplace(ptr, size); clear(lineNo_); lexerStateEOL = this; } @@ -482,12 +497,6 @@ BufferedContent::~BufferedContent() { close(fd); } -MmappedContent::~MmappedContent() { - // FIXME: This never unmaps a referenced file! - if (!isReferenced) - munmap(ptr, size); -} - void lexer_SetMode(LexerMode mode) { lexerState->mode = mode; } @@ -2174,17 +2183,14 @@ static Capture startCapture() { Capture capture = {.lineNo = lexer_GetLineNo(), .body = nullptr, .size = 0}; if (auto *mmap = std::get_if(&lexerState->content); mmap && lexerState->expansions.empty()) { - capture.body = &mmap->ptr[mmap->offset]; + capture.body = std::shared_ptr(mmap->ptr, &mmap->ptr[mmap->offset]); } else if (auto *view = std::get_if(&lexerState->content); view && lexerState->expansions.empty()) { - capture.body = &view->ptr[view->offset]; + capture.body = std::shared_ptr(view->ptr, &view->ptr[view->offset]); } else { // `capture.body == nullptr`; indicates to retrieve the capture buffer when done capturing assert(lexerState->captureBuf == nullptr); - // FIXME: This leaks the captured text! - lexerState->captureBuf = new (std::nothrow) std::vector(); - if (!lexerState->captureBuf) - fatalerror("Failed to allocate capture buffer: %s\n", strerror(errno)); + lexerState->captureBuf = std::make_shared>(); } 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 // during the whole capture process, and so MUST be retrieved at the end if (!capture.body) - capture.body = lexerState->captureBuf->data(); + capture.body = + std::shared_ptr(lexerState->captureBuf, lexerState->captureBuf->data()); capture.size = lexerState->captureSize; // ENDR/ENDM or EOF puts us past the start of the line @@ -2262,10 +2269,6 @@ Capture lexer_CaptureMacro() { 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(&lexerState->content); mmap) - mmap->isReferenced = true; - int c = EOF; for (;;) { diff --git a/src/asm/symbol.cpp b/src/asm/symbol.cpp index fed1fc89..88ab5cee 100644 --- a/src/asm/symbol.cpp +++ b/src/asm/symbol.cpp @@ -74,9 +74,9 @@ int32_t Symbol::getOutputValue() const { } } -std::string_view Symbol::getMacro() const { - assert(std::holds_alternative(data)); - return std::get(data); +std::pair, size_t> Symbol::getMacro() const { + assert((std::holds_alternative, size_t>>(data))); + return std::get, size_t>>(data); } std::shared_ptr Symbol::getEqus() const { @@ -489,14 +489,16 @@ void sym_Export(std::string const &symName) { } // 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 body, size_t size +) { Symbol *sym = createNonrelocSymbol(symName, false); if (!sym) return nullptr; sym->type = SYM_MACRO; - sym->data = std::string_view(body, size); + sym->data = std::make_pair(body, size); sym->src = fstk_GetFileStack(); // The symbol is created at the line after the `ENDM`,