37#include <wx/stdpaths.h>
53 Bracket_Windows =
'%',
61 std::function<bool( wxString* )> projectResolver =
62 [&]( wxString* token ) ->
bool
72 const std::function<
bool( wxString* )>* aResolver,
int aFlags )
75 size_t sourceLen = aSource.length();
77 newbuf.Alloc( sourceLen );
79 for(
size_t i = 0; i < sourceLen; ++i )
81 if( aSource[i] ==
'$' && i + 1 < sourceLen && aSource[i+1] ==
'{' )
85 for( i = i + 2; i < sourceLen; ++i )
87 if( aSource[i] ==
'}' )
90 token.append( aSource[i] );
96 if( ( aFlags &
FOR_ERC_DRC ) == 0 && ( token.StartsWith( wxS(
"ERC_WARNING" ) )
97 || token.StartsWith( wxS(
"ERC_ERROR" ) )
98 || token.StartsWith( wxS(
"DRC_WARNING" ) )
99 || token.StartsWith( wxS(
"DRC_ERROR" ) ) ) )
103 else if( aResolver && (*aResolver)( &token ) )
105 newbuf.append( token );
110 newbuf.append(
"${" + token +
"}" );
115 newbuf.append( aSource[i] );
125 std::function<bool( wxString* )> tokenExtractor =
126 [&]( wxString* token ) ->
bool
138 static wxRegEx expr( wxS(
"^\\$\\{\\w*\\}$" ) );
139 return expr.Matches( aSource );
147 std::set<wxString>* aSet =
nullptr )
152 if(
auto [
_, result ] = aSet->insert( str ); !result )
156 size_t strlen = str.length();
159 strResult.Alloc( strlen );
161 auto getVersionedEnvVar =
162 [](
const wxString& aMatch, wxString& aResult ) ->
bool
166 if( var.Matches( aMatch ) )
168 const auto value = ENV_VAR::GetEnvVar<wxString>( var );
181 for(
size_t n = 0; n < strlen; n++ )
183 wxUniChar str_n = str[n];
185 switch( str_n.GetValue() )
194 if( str_n == wxT(
'%' ) )
196 bracket = Bracket_Windows;
200 if( n == strlen - 1 )
206 switch( str[n + 1].GetValue() )
228 wxUniChar str_m = str[m];
230 while( wxIsalnum( str_m ) || str_m == wxT(
'_' ) || str_m == wxT(
':' ) )
241 wxString strVarName( str.c_str() + n + 1, m - n - 1 );
245 bool expanded =
false;
246 wxString tmp = strVarName;
253 else if( wxGetEnv( strVarName, &tmp ) )
262 else if( strVarName.Contains(
"KISYS3DMOD")
263 || strVarName.Matches(
"KICAD*_3DMODEL_DIR" ) )
265 if( getVersionedEnvVar(
"KICAD*_3DMODEL_DIR", strResult ) )
268 else if( strVarName.Matches(
"KICAD*_SYMBOL_DIR" ) )
270 if( getVersionedEnvVar(
"KICAD*_SYMBOL_DIR", strResult ) )
273 else if( strVarName.Matches(
"KICAD*_FOOTPRINT_DIR" ) )
275 if( getVersionedEnvVar(
"KICAD*_FOOTPRINT_DIR", strResult ) )
278 else if( strVarName.Matches(
"KICAD*_3RD_PARTY" ) )
280 if( getVersionedEnvVar(
"KICAD*_3RD_PARTY", strResult ) )
287 if ( bracket != Bracket_Windows )
290 strResult << str[n - 1];
292 strResult << str_n << strVarName;
298 if( m == strlen || str_m != (wxChar)bracket )
307 wxLogWarning(
_(
"Environment variables expansion failed: missing '%c' "
308 "at position %u in '%s'." ),
309 (
char)bracket, (
unsigned int) (m + 1), str.c_str() );
316 strResult << (wxChar)bracket;
329 if( n < strlen - 1 && (str[n + 1] == wxT(
'%' ) || str[n + 1] == wxT(
'$' ) ) )
344 std::set<wxString> loop_check;
345 auto first_pos = strResult.find_first_of( wxS(
"{(%" ) );
346 auto last_pos = strResult.find_last_of( wxS(
"})%" ) );
348 if( first_pos != strResult.npos && last_pos != strResult.npos && first_pos != last_pos )
359 static std::mutex getenv_mutex;
361 std::lock_guard<std::mutex> lock( getenv_mutex );
377 const wxString& aBaseFilename,
381 wxString baseFilePath = wxFileName( aBaseFilename ).GetPath();
385 if( !aTargetFullFileName->MakeAbsolute( baseFilePath ) )
389 msg.Printf(
_(
"Cannot make path '%s' absolute with respect to '%s'." ),
390 aTargetFullFileName->GetPath(),
399 wxString outputPath( aTargetFullFileName->GetPath() );
401 if( !wxFileName::DirExists( outputPath ) )
404 if( wxFileName::Mkdir( outputPath, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
408 msg.Printf(
_(
"Output directory '%s' created." ), outputPath );
417 msg.Printf(
_(
"Cannot create output directory '%s'." ), outputPath );
431 wxString newFilename( aFilename );
436 if( newFilename.Lower().AfterLast(
'.' ) != aExtension )
438 if( !newFilename.EndsWith(
'.' ) )
439 newFilename.Append(
'.' );
441 newFilename.Append( aExtension );
478 if( dot_special && (*n ==
'.') )
575#if wxUSE_DATETIME && defined( __WIN32__ ) && !defined( __WXMICROWIN__ )
581static wxInt64 EPOCH_OFFSET_IN_MSEC = wxLL( 11644473600000 );
584static void ConvertFileTimeToWx( wxDateTime* dt,
const FILETIME& ft )
586 wxLongLong t( ft.dwHighDateTime, ft.dwLowDateTime );
588 t -= EPOCH_OFFSET_IN_MSEC;
590 *dt = wxDateTime( t );
604long long TimestampDir(
const wxString& aDirPath,
const wxString& aFilespec )
606 long long timestamp = 0;
608#if defined( __WIN32__ )
613 std::wstring filespec( aDirPath.t_str() );
615 filespec += aFilespec.t_str();
617 WIN32_FIND_DATA findData;
618 wxDateTime lastModDate;
620 HANDLE fileHandle = ::FindFirstFile( filespec.data(), &findData );
622 if( fileHandle != INVALID_HANDLE_VALUE )
626 ConvertFileTimeToWx( &lastModDate, findData.ftLastWriteTime );
627 timestamp += lastModDate.GetValue().GetValue();
630 timestamp += findData.nFileSizeLow;
632 while ( FindNextFile( fileHandle, &findData ) != 0 );
635 FindClose( fileHandle );
639 std::string filespec( aFilespec.fn_str() );
640 std::string dir_path( aDirPath.fn_str() );
642 DIR* dir = opendir( dir_path.c_str() );
646 for( dirent* dir_entry = readdir( dir ); dir_entry; dir_entry = readdir( dir ) )
648 if( !
matchWild( filespec.c_str(), dir_entry->d_name,
true ) )
651 std::string entry_path = dir_path +
'/' + dir_entry->d_name;
652 struct stat entry_stat;
654 if( wxCRT_Lstat( entry_path.c_str(), &entry_stat ) == 0 )
657 if( S_ISLNK( entry_stat.st_mode ) )
659 char buffer[ PATH_MAX + 1 ];
660 ssize_t pathLen = readlink( entry_path.c_str(), buffer, PATH_MAX );
664 struct stat linked_stat;
665 buffer[ pathLen ] =
'\0';
666 entry_path = dir_path + buffer;
668 if( wxCRT_Lstat( entry_path.c_str(), &linked_stat ) == 0 )
670 entry_stat = linked_stat;
680 if( S_ISREG( entry_stat.st_mode ) )
682 timestamp += entry_stat.st_mtime * 1000;
685 timestamp += entry_stat.st_size;
691 timestamp += (signed) std::hash<std::string>{}( std::string( dir_entry->d_name ) );
708 wxMessageDialog dialog(
nullptr,
_(
"This operating system is not supported "
709 "by KiCad and its dependencies." ),
710 _(
"Unsupported Operating System" ),
711 wxOK | wxICON_EXCLAMATION );
713 dialog.SetExtendedMessage(
_(
"Any issues with KiCad on this system cannot "
714 "be reported to the official bugtracker." ) );
Container for project specific data.
virtual bool TextVarResolver(wxString *aToken) const
A pure virtual class used to derive REPORTER objects from.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
wxString GetGeneratedFieldDisplayName(const wxString &aSource)
Returns any variables unexpanded, e.g.
const wxString ResolveUriByEnvVars(const wxString &aUri, const PROJECT *aProject)
Replace any environment and/or text variables in URIs.
wxString EnsureFileExtension(const wxString &aFilename, const wxString &aExtension)
It's annoying to throw up nag dialogs when the extension isn't right.
bool WarnUserIfOperatingSystemUnsupported()
Checks if the operating system is explicitly unsupported and displays a disclaimer message box.
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
bool matchWild(const char *pat, const char *text, bool dot_special)
Performance enhancements to file and directory operations.
bool EnsureFileDirectoryExists(wxFileName *aTargetFullFileName, const wxString &aBaseFilename, REPORTER *aReporter)
Make aTargetFullFileName absolute and create the path of this file if it doesn't yet exist.
wxString KIwxExpandEnvVars(const wxString &str, const PROJECT *aProject, std::set< wxString > *aSet=nullptr)
bool IsGeneratedField(const wxString &aSource)
Returns true if the string is generated, e.g contains a single text var reference.
long long TimestampDir(const wxString &aDirPath, const wxString &aFilespec)
A copy of ConvertFileTimeToWx() because wxWidgets left it as a static function private to src/common/...
#define FOR_ERC_DRC
Expand '${var-name}' templates in text.
Base window classes and related definitions.
Functions related to environment variables, including help functions.
This file contains miscellaneous commonly used macros and functions.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
KICOMMON_API const std::vector< wxString > & GetPredefinedEnvVars()
Get the list of pre-defined environment variables.