📄 loginfo.cc
字号:
//=======================================================================// LogInfo.cc//-----------------------------------------------------------------------// This file is part of the package paco// Copyright (C) 2004-2007 David Rosal <david.3r@gmail.com>// For more information visit http://paco.sourceforge.net//=======================================================================#include "config.h"#include "global.h"#include "LogInfo.h"#include "Log.h"#include "Pkg.h"#include <iostream>#include <fstream>#include <sstream>#include <vector>#include <string>#include <glob.h>using std::endl;using std::string;using std::vector;using std::set;using namespace Paco;// Forward declarationsstatic string getVar(string const&, string const&);static string getBuildVar(string const&);static string stripTrailingDot(string const&);LogInfo::LogInfo(Log& log): mIcon(), mOpts(), mName(), mVersion(), mAuthor(), mSummary(), mUrl(), mLicense(), mDesc(), mPkg(log.mPkgName), mBase(Pkg::getBase(mPkg)), mDesktopFile(), mDef(), mDirs(), mFiles(log.mFiles){ gOut.dbgTitle("information"); getDirs(); mDesktopFile = searchFile(mBase, ".desktop"); getIcon(); getInfoSpec(); getInfoAspec(); getInfoPC(); getInfoDesktop(); getConfigOpts(); if (mName.empty()) mName = mBase; if (mVersion.empty()) mVersion = Pkg::getVersion(mPkg); writeInfo(); if (gOut.verbosity() > Out::VERBOSE) printInfo();}LogInfo::Define::Define(char const fmt, string const& var, string const& val): mFmt(fmt), mVar(var), mVal(val){ }void LogInfo::Define::resolve(string& str) const{ if (str.find(mFmt) == string::npos) return; string::size_type p; string var0(1, mFmt); string var1(1, mFmt); var0 += mVar; var1 += "{" + mVar + "}"; for (p = 0; (p = str.find(var0, p)) != string::npos; ) str.replace(p, var0.size(), mVal); for (p = 0; (p = str.find(var1, p)) != string::npos; ) str.replace(p, var1.size(), mVal);}string& LogInfo::resolveDefines(string& str) const{ for (uint i = 0; i < mDef.size(); ++i) mDef[i].resolve(str); return str;}void LogInfo::getSpecDefines(string const& spec){ std::ifstream f(spec.c_str()); if (!f) return; char* var; char* p; char* val; char buf[8192]; while (!f.getline(buf, sizeof(buf)).eof()) { if ((p = strtok(buf, " \t")) && !strcmp(p, "%define") && (var = strtok(NULL, " \t\n")) && (val = strtok(NULL, " \t\n")) && val[0] != '%') mDef.push_back(Define(Define::FMT_SPEC, var, val)); }}void LogInfo::getPCDefines(string const& pc){ std::ifstream f(pc.c_str()); if (!f) return; string buf; string::size_type p; while (getline(f, buf)) { if ((p = buf.find("=")) != string::npos && buf.size() > p) { mDef.push_back(Define(Define::FMT_PC, buf.substr(0, p), buf.substr(p + 1))); } }}bool LogInfo::getInfoVar(string const& file, string const& tag, string& info) const{ if (!info.empty()) return true; std::ifstream f(file.c_str()); if (!f) return false; string buf; string::size_type p; while (getline(f, buf) && info.empty()) { if (!buf.find(tag) && (p = buf.find_first_not_of(" \t:=", tag.size())) != string::npos) { buf.erase(0, p); resolveDefines(buf); // avoid @foo@, %{foo} and ${foo} if (!((buf.at(0) == '@' && buf.at(buf.size() - 1) == '@') || ((p = buf.find("%{")) != string::npos && buf.find('}', p) != string::npos) || ((p = buf.find("${")) != string::npos && buf.find('}', p) != string::npos))) { info = buf; } } } return !info.empty();}void LogInfo::getDescription(string const& spec, string const& title){ if (!mDesc.empty()) return; std::ifstream f(spec.c_str()); if (!f) return; string buf; while (getline(f, buf) && buf.find(title) != 0); if (f.eof()) return; bool emptyLine = false; while (getline(f, buf) && buf[0] != title[0] && buf[0] != '#') { if (buf.empty()) { if (!emptyLine && !mDesc.empty()) mDesc += "\n#:"; emptyLine = true; } else { mDesc += resolveDefines(buf) + (buf.size() < 48 ? "\n#:" : " "); emptyLine = false; } } if (mDesc.size() < 8) mDesc.clear();}void LogInfo::getInfoAspec(){ string aspec(searchFile(mBase, ".aspec")); if (aspec.empty()) return; getInfoVar(aspec, "ShortName", mName); getInfoVar(aspec, "PackageVersion", mVersion); getInfoVar(aspec, "URL", mUrl); getInfoVar(aspec, "License", mLicense); getDescription(aspec, "[Description]"); if (!getInfoVar(aspec, "Maintainer", mAuthor)) getInfoVar(aspec, "Packager", mAuthor); if (!getInfoVar(aspec, "Summary", mSummary)) getInfoVar(aspec, "DisplayName", mSummary);}void LogInfo::getInfoSpec(){ string spec(searchFile(mBase, ".spec")); if (spec.empty()) return; getSpecDefines(spec); getInfoVar(spec, "Name", mName); getInfoVar(spec, "Version", mVersion); getInfoVar(spec, "Summary", mSummary); getInfoVar(spec, "URL", mUrl); getInfoVar(spec, "Icon", mIcon); getDescription(spec, "%description"); if (!getInfoVar(spec, "Vendor", mAuthor)) getInfoVar(spec, "Packager", mAuthor); if (!getInfoVar(spec, "License", mLicense)) getInfoVar(spec, "Copyright", mLicense);}void LogInfo::getInfoDesktop(){ if (mDesktopFile.empty()) return; getInfoVar(mDesktopFile, "Name", mName); if (!getInfoVar(mDesktopFile, "Comment", mSummary)) getInfoVar(mDesktopFile, "GenericName", mSummary);}void LogInfo::getInfoPC(){ string pc(searchFile(mBase, ".pc")); if (pc.empty()) return; getPCDefines(pc); getInfoVar(pc, "Name", mName); getInfoVar(pc, "Version", mVersion); getInfoVar(pc, "Description", mSummary);}string LogInfo::searchFile( string const& name, string const& suffix /* = "" */) const{ if (name.empty()) return name; gOut.dbg("searching " + name + suffix); glob_t g; memset(&g, 0, sizeof(g)); string file, pat[2] = { "*/*/" + name + suffix, "*/*/" + name + "-[0-9]*" + suffix }; for (uint i = 0; i < 2; ++i) { for (set<string>::iterator d = mDirs.begin(); d != mDirs.end(); ++d) { for (int k = 2; k >= 0; --k) { string s = *d + "/" + pat[i].substr(k << 1); if (!glob(s.c_str(), GLOB_NOSORT, 0, &g) && g.gl_pathc) { file = g.gl_pathv[0]; goto ____return; } } } } ____return: globfree(&g); if (file.empty()) gOut.dbg("\t(not found)\n", false); else gOut.dbg("\t" + file + "\n", false); return file;}void LogInfo::getConfigOpts(){ if (!mOpts.empty()) return; string configLog(searchFile("config.log")); if (configLog.empty()) return; std::ifstream f(configLog.c_str()); if (!f) return; string buf; string::size_type p; while (getline(f, buf) && mOpts.empty()) { if ((p = buf.find("$")) != string::npos && (p = buf.find("/configure", p)) != string::npos && (p = buf.find("--", p)) != string::npos) mOpts = buf.substr(p); }}void LogInfo::getIcon(){ char const* fmt[] = { ".png", ".xpm", ".jpg", ".ico", ".gif", ".svg", 0 }; string::size_type p = string::npos; // First search for the name of the icon in the .desktop file mIcon = getVar(mDesktopFile, "Icon"); if (!mIcon.empty()) { for (uint i = 0; p == string::npos && fmt[i]; ++i) p = mIcon.find(fmt[i]); if (p == string::npos) mIcon.clear(); } // Next search for the icon file within the source tree if (mIcon.empty()) { Out::Silencer s; for (uint i = 0; fmt[i] && mIcon.empty(); ++i) mIcon = searchFile(mBase, fmt[i]); } // Search the logged files for the path of the icon if ((p = mIcon.rfind("/")) != string::npos) mIcon.erase(0, p + 1); bool ok = false; for (set<string>::iterator i = mFiles.begin(); i != mFiles.end(); ++i) { if (matchIcon(*i, fmt)) { mIcon = *i; ok = true; break; } } if (!ok) mIcon.clear();}bool LogInfo::matchIcon(string const& path, char const* fmt[]){ if (!mIcon.empty()) return (path.find("/" + mIcon) == path.size() - mIcon.size() - 1); string::size_type p; for (uint i = 0; fmt[i]; ++i) { string icon("/" + mBase + fmt[i]); if ((p = path.find(icon)) != string::npos) { if (path.substr(p) == icon) return true; } } return false;}void LogInfo::getDirs(){ mDirs.insert("."); string dir; if ((dir = getBuildVar("top_srcdir")).size()) mDirs.insert(dir); if ((dir = getBuildVar("top_builddir")).size()) mDirs.insert(dir);}void LogInfo::writeInfo() const{ FileStream<std::ofstream> f(Config::logdir() + "/" + mPkg); f << "#!paco-" PACKAGE_VERSION "\n#d:" << time(0) << "\n"; if (!mOpts.empty()) f << "#c:" << mOpts << "\n"; if (!mIcon.empty()) f << "#i:" << mIcon << "\n"; if (!mName.empty()) f << "#:Name: " << mName << "\n"; if (!mVersion.empty()) f << "#:Version: " << mVersion << "\n"; if (!mAuthor.empty()) f << "#:Author: " << mAuthor << "\n"; if (!mSummary.empty()) f << "#:Summary: " << stripTrailingDot(mSummary) << "\n"; if (!mUrl.empty()) f << "#:URL: " << mUrl << "\n"; if (!mLicense.empty()) f << "#:License: " << mLicense << "\n"; if (!mDesc.empty()) f << "#:\n#:Description\n#:" << mDesc << "\n";}void LogInfo::printInfo() const{ gOut.dbgTitle(""); gOut.dbg("Name: " + mName + "\n"); gOut.dbg("Version: " + mVersion + "\n"); gOut.dbg("Author: " + mAuthor + "\n"); gOut.dbg("Summary: " + mSummary + "\n"); gOut.dbg("URL: " + mUrl + "\n"); gOut.dbg("License: " + mLicense + "\n"); gOut.dbg("Conf. opts: " + mOpts + "\n"); gOut.dbg("Icon: " + mIcon + "\n"); gOut.dbg("Description: "); std::ostringstream s; if (!mDesc.empty()) s << "(" << mDesc.size() << " chars written)"; gOut.dbg(s.str() + "\n", false); gOut.dbgTitle("");}static string getVar(string const& file, string const& tag){ std::ifstream f(file.c_str()); if (!f) return ""; string::size_type p; string buf; string var; while (getline(f, buf) && var.empty()) { if (!buf.find(tag) && (p = buf.find_first_not_of(" =\t\n", tag.size())) != string::npos) var = buf.substr(p); } return var;}//// Extract the value of 'var' from Makefile, makefile or config.log//static string getBuildVar(string const& var){ string v = getVar("Makefile", var); if (v.empty()) v = getVar("makefile", var); if (v.empty()) v = getVar("config.log", var); return v;}static string stripTrailingDot(string const& s){ if (s.size() && s.at(s.size() - 1) == '.') return s.substr(0, s.size() - 1); return s;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -