From dc645a36aaade7087ade574cefe69ce7bb29753e Mon Sep 17 00:00:00 2001 From: _ov4 Date: Sat, 17 Oct 2026 09:09:03 +0000 Subject: refactor(diag): file-qualified diagnostic locations Co-Authored-By: Claude Opus 5.5 --- include/cps/Diagnostics.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 include/cps/Diagnostics.h (limited to 'include') diff --git a/include/cps/Diagnostics.h b/include/cps/Diagnostics.h new file mode 100644 index 0000000..6f26292 --- /dev/null +++ b/include/cps/Diagnostics.h @@ -0,0 +1,44 @@ +#pragma once +#include +#include +#include +#include + +namespace cps { +// Empty for single-source builds to preserve existing diagnostic text. +inline std::string DiagnosticSource; +inline std::string lineSuffix(int Line) { + return " at line " + std::to_string(Line) + + (DiagnosticSource.empty() ? "" : " in " + DiagnosticSource); +} +inline void sourceDiagnostic(int Line, const char *Format, ...) { + va_list Args, Copy; + va_start(Args, Format); + va_copy(Copy, Args); + int Size = std::vsnprintf(nullptr, 0, Format, Copy); + va_end(Copy); + if (Size < 0) { va_end(Args); return; } + std::vector Buffer(Size + 1); + std::vsnprintf(Buffer.data(), Buffer.size(), Format, Args); + va_end(Args); + std::string Message(Buffer.data(), Size); + if (!DiagnosticSource.empty()) { + auto At = Message.find("at line "); + if (At != std::string::npos) { + auto End = Message.find_first_not_of("0123456789", At + 8); + Message.insert(End == std::string::npos ? Message.size() : End, + " in " + DiagnosticSource); + } else { + auto Old = Message.find("(line "); + if (Old != std::string::npos) { + auto End = Message.find(')', Old); + Message.replace(Old, End - Old + 1, lineSuffix(Line).substr(1)); + } else { + auto End = Message.find_last_not_of("\n"); + Message.insert(End == std::string::npos ? 0 : End + 1, lineSuffix(Line)); + } + } + } + std::fputs(Message.c_str(), stderr); +} +} -- cgit v1.3.1-4-g156e