3838*/
3939
4040#include " nabla.h"
41+ #include < boost/exception/diagnostic_information.hpp>
4142
4243using namespace nbl ;
4344using namespace nbl ::asset;
4445
4546#include " nbl/asset/utils/waveContext.h"
4647
48+ namespace
49+ {
50+ std::string getLineSnippet (std::string_view text, const int lineNo)
51+ {
52+ if (lineNo <= 0 )
53+ return {};
54+
55+ int currentLine = 1 ;
56+ size_t lineStart = 0ull ;
57+ while (lineStart <= text.size ())
58+ {
59+ const auto lineEnd = text.find (' \n ' , lineStart);
60+ if (currentLine == lineNo)
61+ {
62+ const auto count = lineEnd == std::string_view::npos ? text.size () - lineStart : lineEnd - lineStart;
63+ auto line = std::string (text.substr (lineStart, count));
64+ if (!line.empty () && line.back () == ' \r ' )
65+ line.pop_back ();
66+ return line;
67+ }
68+
69+ if (lineEnd == std::string_view::npos)
70+ break ;
71+ lineStart = lineEnd + 1ull ;
72+ currentLine++;
73+ }
74+
75+ return {};
76+ }
77+
78+ std::string makeCaretLine (const int columnNo)
79+ {
80+ if (columnNo <= 0 )
81+ return {};
82+
83+ return std::string (static_cast <size_t >(columnNo - 1 ), ' ' ) + ' ^' ;
84+ }
85+
86+ std::string makeWaveFailureContext (
87+ const nbl::asset::IShaderCompiler::SPreprocessorOptions& preprocessOptions,
88+ const std::string_view code,
89+ const char * const phase,
90+ const std::string_view activeMacroDefinition,
91+ const char * const fileName,
92+ const int lineNo,
93+ const int columnNo)
94+ {
95+ std::ostringstream stream;
96+ stream << " Wave preprocessing context:" ;
97+ if (!preprocessOptions.sourceIdentifier .empty ())
98+ stream << " \n source: " << preprocessOptions.sourceIdentifier ;
99+ stream << " \n phase: " << phase;
100+ stream << " \n extra_define_count: " << preprocessOptions.extraDefines .size ();
101+ stream << " \n source_has_trailing_newline: " << ((!code.empty () && code.back () == ' \n ' ) ? " yes" : " no" );
102+ if (!activeMacroDefinition.empty ())
103+ stream << " \n active_macro_definition: " << activeMacroDefinition;
104+ if (fileName && fileName[0 ] != ' \0 ' )
105+ stream << " \n location: " << fileName << ' :' << lineNo << ' :' << columnNo;
106+
107+ const auto snippet = getLineSnippet (code, lineNo);
108+ if (!snippet.empty () && fileName && preprocessOptions.sourceIdentifier == fileName)
109+ {
110+ stream << " \n snippet: " << snippet;
111+ const auto caret = makeCaretLine (columnNo);
112+ if (!caret.empty ())
113+ stream << " \n " << caret;
114+ }
115+
116+ return stream.str ();
117+ }
118+ }
119+
47120namespace nbl ::wave
48121{
49122 std::string preprocess (std::string& code, const nbl::asset::IShaderCompiler::SPreprocessorOptions& preprocessOptions, bool withCaching, std::function<void (nbl::wave::context&)> post)
@@ -61,29 +134,51 @@ namespace nbl::wave
61134
62135 // preprocess
63136 core::string resolvedString;
137+ const char * phase = " registering built-in macros" ;
138+ std::string activeMacroDefinition;
64139 try
65140 {
141+ phase = " registering extra macro definitions" ;
66142 for (const auto & define : preprocessOptions.extraDefines )
67143 {
68- std::string macroDefinition ( define.identifier ) ;
69- macroDefinition .push_back (' =' );
70- macroDefinition .append (define.definition );
71- context.add_macro_definition (macroDefinition );
144+ activeMacroDefinition = define.identifier ;
145+ activeMacroDefinition .push_back (' =' );
146+ activeMacroDefinition .append (define.definition );
147+ context.add_macro_definition (activeMacroDefinition );
72148 }
149+ activeMacroDefinition.clear ();
73150
151+ phase = " expanding translation unit" ;
74152 auto stream = std::stringstream ();
75153 for (auto i = context.begin (); i != context.end (); i++)
76154 stream << i->get_value ();
77155 resolvedString = stream.str ();
78156 }
79157 catch (boost::wave::preprocess_exception& e)
80158 {
81- preprocessOptions.logger .log (" %s exception caught. %s [%s:%d:%d]" ,system::ILogger::ELL_ERROR,e.what (),e.description (),e.file_name (),e.line_no (),e.column_no ());
159+ const auto failureContext = makeWaveFailureContext (preprocessOptions, code, phase, activeMacroDefinition, e.file_name (), e.line_no (), e.column_no ());
160+ preprocessOptions.logger .log (" %s exception caught. %s [%s:%d:%d]\n %s" , system::ILogger::ELL_ERROR, e.what (), e.description (), e.file_name (), e.line_no (), e.column_no (), failureContext.c_str ());
161+ preprocessOptions.logger .log (" Boost diagnostic information:\n %s" , system::ILogger::ELL_ERROR, boost::diagnostic_information (e).c_str ());
162+ return {};
163+ }
164+ catch (const boost::exception& e)
165+ {
166+ const auto failureContext = makeWaveFailureContext (preprocessOptions, code, phase, activeMacroDefinition, preprocessOptions.sourceIdentifier .data (), 0 , 0 );
167+ preprocessOptions.logger .log (" Boost exception caught during Wave preprocessing.\n %s" , system::ILogger::ELL_ERROR, failureContext.c_str ());
168+ preprocessOptions.logger .log (" Boost diagnostic information:\n %s" , system::ILogger::ELL_ERROR, boost::diagnostic_information (e).c_str ());
169+ return {};
170+ }
171+ catch (const std::exception& e)
172+ {
173+ const auto failureContext = makeWaveFailureContext (preprocessOptions, code, phase, activeMacroDefinition, preprocessOptions.sourceIdentifier .data (), 0 , 0 );
174+ preprocessOptions.logger .log (" std::exception caught during Wave preprocessing. %s\n %s" , system::ILogger::ELL_ERROR, e.what (), failureContext.c_str ());
82175 return {};
83176 }
84177 catch (...)
85178 {
86- preprocessOptions.logger .log (" Unknown exception caught!" ,system::ILogger::ELL_ERROR);
179+ const auto failureContext = makeWaveFailureContext (preprocessOptions, code, phase, activeMacroDefinition, preprocessOptions.sourceIdentifier .data (), 0 , 0 );
180+ preprocessOptions.logger .log (" Unknown exception caught during Wave preprocessing.\n %s" , system::ILogger::ELL_ERROR, failureContext.c_str ());
181+ preprocessOptions.logger .log (" Current exception diagnostic information:\n %s" , system::ILogger::ELL_ERROR, boost::current_exception_diagnostic_information ().c_str ());
87182 return {};
88183 }
89184
0 commit comments