void FileLocator::addPathFromFile(const char* fileName) { /* Find the final '/': */ const char* slashPtr=findLastOf(fileName,'/'); if(slashPtr!=0) { /* Add the file's directory to the search path list: */ addPath(fileName,slashPtr); } else { /* Add the current directory to the search path list: */ pathList.push_back(getCurrentDirectory()); } }
void FileLocator::addPathFromApplication(const char* executablePath) { /* Separate the executable name from the executable path: */ const char* slashPtr=findLastOf(executablePath,'/'); std::string appName=slashPtr!=0?std::string(slashPtr+1):std::string(executablePath); /* Add the standard resource search path for private installed applications: */ if(getenv("HOME")!=0) { std::string path=getenv("HOME"); path.append("/."); path.append(appName); addPath(path); } /* Add the standard resource search paths for system-wide installed applications: */ addPath("/usr/share/"+appName); addPath("/usr/local/share/"+appName); /* Construct the fully-qualified executable name: */ std::string fullExePath; if(executablePath[0]=='/') fullExePath=executablePath; else { /* Try to find the full path to the executable: */ #if 0 /* Get the full executable path through the /proc interface: */ char pse[PATH_MAX]; int pseLength=readlink("/proc/self/exe",pse,PATH_MAX); if(pseLength>=0) fullExePath=std::string(pse,pse+pseLength); else { #else /* Search for the executable just as the shell did: */ if(slashPtr==0&&getenv("PATH")!=0) { /* Search for the executable in the PATH list: */ const char* pathBegin=getenv("PATH"); while(*pathBegin!='\0') { /* Find the end of the next path: */ const char* pathEnd; for(pathEnd=pathBegin;*pathEnd!='\0'&&*pathEnd!=':';++pathEnd) ; /* Test the path if it is non-empty: */ if(pathEnd!=pathBegin) { /* Construct the full path name: */ std::string testName; if(*pathBegin!='/') { /* Start the path name with the current directory: */ testName=getCurrentDirectory(); testName.push_back('/'); } testName.append(pathBegin,pathEnd); testName.push_back('/'); testName.append(appName); /* Test if the file exists and is an executable: */ if(Misc::isPathFile(testName.c_str())) { /* Save the matching full path and stop searching: */ fullExePath=testName; break; } } /* Go to the next path: */ if(*pathEnd!='\0') ++pathEnd; pathBegin=pathEnd; } } else { /* Use the provided path starting at the current directory: */ fullExePath=getCurrentDirectory(); fullExePath.push_back('/'); fullExePath.append(executablePath); } #endif #if 0 } #endif } /* Find the last slash in the cleaned fully-qualified executable path name: */ std::string cleanFullExePath=cleanPath(fullExePath.c_str()); executablePath=cleanFullExePath.c_str(); slashPtr=findLastOf(executablePath,'/'); #ifdef __linux__ /* Check if the executable is part of a Linux application bundle: */ if(slashPtr!=0) { if(slashPtr-executablePath>=4&&strncasecmp(slashPtr-4,"/exe",4)==0) { /* Add the bundle's base directory to the search path list: */ addPath(executablePath,slashPtr-4); } else if(slashPtr-executablePath>=7&&strncasecmp(slashPtr-7,"/exe/64",7)==0) { /* Add the bundle's base directory to the search path list: */ addPath(executablePath,slashPtr-7); } } #endif #ifdef __APPLE__ /* Check if the executable is part of a Mac OS X application bundle: */ if(slashPtr!=0&&slashPtr-executablePath>=19&&strncasecmp(slashPtr-19,".app/Contents/MacOS",19)==0) { /* Add the bundle's resource directory to the search path list: */ addPath(std::string(executablePath,slashPtr-5)+"Resources"); } #endif }
void Logfile::writeLine(const String& caller, const UnicodeString& lineContent, OutputType type, bool writeTimestamp) { auto lock = ScopedMutexLock(m->mutex); m->currentOutputType = type; // Open div for this output type *this << "<div class='"; if (type == Info) *this << "info"; else if (type == Debug) *this << "debug"; else if (type == Warning) *this << "warning"; else if (type == Error) *this << "error"; else if (type == Console) *this << "console"; *this << "'>"; m->isHookingEnabled = true; if (writeTimestamp) *this << "[" << FileSystem::getShortDateTime() << "] "; // Add the prefix for this output type if (type == Warning) *this << "Warning: "; else if (type == Error) *this << "Error: "; if (caller.length()) { // Format the result of CARBON_CURRENT_FUNCTION in a consistent way across all platforms. // CARBON_CURRENT_FUNCTION uses either __FUNCTION__ or __PRETTY_FUNCTION__ depending on the compiler. Aim for a // string in the format Class::Method() regardless of which macro the name originated from. auto formattedCaller = caller; // Cut off everything after the final ')' auto index = formattedCaller.findLastOf(")"); if (index != -1) { formattedCaller = formattedCaller.substr(0, index + 1); // Cut out all the parameter type information. Parentheses need to be counted to determine where the // parameter type information stops because function pointer parameters will have parentheses in them. auto parenthesisCount = 0; for (auto i = int(formattedCaller.length()) - 1; i >= 0; i--) { if (formattedCaller.at(i) == ')') parenthesisCount++; else if (formattedCaller.at(i) == '(') { parenthesisCount--; if (parenthesisCount <= 0) { formattedCaller = formattedCaller.substr(0, i); break; } } } } // Cut out the return type information if present index = formattedCaller.findLastOf(String::Space); if (index != -1) { formattedCaller = formattedCaller.substr(index + 1); formattedCaller.trimLeft("*&"); } *this << formattedCaller.withoutPrefix("Carbon::") << "() - "; } *this << lineContent << UnicodeString::Newline; m->isHookingEnabled = false; *this << "</div>"; #ifdef CARBON_DEBUG // Trigger assertions on warnings/errors if enabled if (type == Warning && AssertOnWarnings) assert(false && "Asserting because a warning was reported"); else if (type == Error && AssertOnErrors) assert(false && "Asserting because an error was reported"); #endif }