From: Andreas Oberritter Date: Mon, 1 Nov 2010 13:36:06 +0000 (+0100) Subject: bsod: use simple XML generator X-Git-Url: http://code.vuplus.com/gitweb/?p=vuplus_dvbapp;a=commitdiff_plain;h=728f5f70f2ece1e2ac1e70cf5a3512b6cfd8cd83 bsod: use simple XML generator --- diff --git a/configure.ac b/configure.ac index 25589c2..c2d8d91 100644 --- a/configure.ac +++ b/configure.ac @@ -34,6 +34,9 @@ AX_PTHREAD TUXBOX_APPS_DVB +AM_CONDITIONAL(HAVE_GIT_DIR, test -d "$srcdir/.git") +AM_CONDITIONAL(HAVE_FAKE_GIT_DIR, test -f "$srcdir/.git/last_commit_info") + PKG_CHECK_MODULES(BASE, [freetype2 fribidi gstreamer-0.10 gstreamer-pbutils-0.10 libdvbsi++ libpng libxml-2.0 sigc++-1.2]) PKG_CHECK_MODULES(LIBDDVD, libdreamdvd, HAVE_LIBDDVD="yes", HAVE_LIBDDVD="no") AM_CONDITIONAL(HAVE_LIBDDVD, test "$HAVE_LIBDDVD" = "yes") diff --git a/main/Makefile.am b/main/Makefile.am index c96f906..782138e 100644 --- a/main/Makefile.am +++ b/main/Makefile.am @@ -13,6 +13,10 @@ enigma2_SOURCES = \ bsod.cpp \ bsod.h \ enigma.cpp \ + xmlgenerator.cpp \ + xmlgenerator.h \ + version_info.cpp \ + version_info.h version.h EXTRA_DIST = \ @@ -48,27 +52,29 @@ enigma2_LDADD = \ enigma2_LDFLAGS = -Wl,--export-dynamic -BUILT_SOURCES = version.h - +if HAVE_GIT_DIR GIT_DIR = $(top_srcdir)/.git +GIT = git --git-dir=$(GIT_DIR) -version.h: - if [ -d $(GIT_DIR) ]; then \ - if [ -f $(GIT_DIR)/last_commit_info ]; then \ - echo "#define ENIGMA2_LAST_CHANGE_DATE \"`cat $(GIT_DIR)/last_commit_info | grep 'Date:' | cut -d' ' -f4`\"" > $@; \ - echo "#define ENIGMA2_BRANCH \"`cat $(GIT_DIR)/branch`\"" >> $@; \ - else \ - echo "#define ENIGMA2_LAST_CHANGE_DATE \"`git --git-dir=$(top_srcdir)/.git log --no-color -n 1 --format=format:%cd --date=short`\"" > $@; \ - echo "#define ENIGMA2_BRANCH \"`git --git-dir=$(top_srcdir)/.git branch --no-color 2>/dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/'`\"" >> $@; \ - fi; \ - elif [ ! -f $@ ]; then \ - echo "#define ENIGMA2_LAST_CHANGE_DATE \"`date --rfc-3339=date`\"" > $@; \ - echo "#define ENIGMA2_BRANCH \"$(PACKAGE_VERSION)\"" >> $@; \ - fi; +if HAVE_FAKE_GIT_DIR +ENIGMA2_DATE = `cat $(GIT_DIR)/last_commit_info | grep 'Date:' | cut -d' ' -f4` +ENIGMA2_BRANCH = `cat $(GIT_DIR)/branch` +else +ENIGMA2_DATE = `$(GIT) log --no-color -n 1 --format=format:%cd --date=short` +ENIGMA2_BRANCH = `$(GIT) branch --no-color 2>/dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/'` +ENIGMA2_REV = `$(GIT) describe --abbrev=7 --always --dirty --long --tags` +endif -dist-hook: - echo "#define ENIGMA2_LAST_CHANGE_DATE \"`date --rfc-3339=date`\"" > version.h; - echo "#define ENIGMA2_BRANCH \"$(PACKAGE_VERSION)\"" >> version.h; +BUILT_SOURCES = version-intermediate.h +CLEANFILES = version-intermediate.h +version-intermediate.h: + $(AM_V_GEN)touch $@ + $(AM_V_at)[ -n "$(ENIGMA2_DATE)" ] && echo "#define ENIGMA2_LAST_CHANGE_DATE \"$(ENIGMA2_DATE)\"" >> $@ + $(AM_V_at)[ -n "$(ENIGMA2_BRANCH)" ] && echo "#define ENIGMA2_BRANCH \"$(ENIGMA2_BRANCH)\"" >> $@ + $(AM_V_at)[ -n "$(ENIGMA2_REV)" ] && echo "#define ENIGMA2_REV \"$(ENIGMA2_REV)\"" >> $@ + $(AM_V_at)([ -f version.h ] && diff -q version.h $@ >/dev/null) || $(INSTALL_HEADER) $@ version.h + $(AM_V_at)$(RM) $@ +endif enigma2$(EXEEXT): $(enigma2_OBJECTS) $(enigma2_DEPENDENCIES) $(enigma2_LDADD_WHOLE) $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ $(enigma2_LDFLAGS) $(enigma2_OBJECTS) \ diff --git a/main/bsod.cpp b/main/bsod.cpp old mode 100755 new mode 100644 index 40252c0..7256d20 --- a/main/bsod.cpp +++ b/main/bsod.cpp @@ -1,45 +1,51 @@ -#include -#include -#include - +#include +#include #include #include -#include #include -#include #include -#include "version.h" +#if defined(__MIPSEL__) +#include +#else +#warning "no oops support!" +#define NO_OOPS_SUPPORT +#endif + +#include "xmlgenerator.h" +#include "version_info.h" /************************************************/ #define CRASH_EMAILADDR "crashlog@dream-multimedia-tv.de" -#define STDBUFFER_SIZE 512 +#define INFOFILE "/maintainer.info" + #define RINGBUFFER_SIZE 16384 static char ringbuffer[RINGBUFFER_SIZE]; -static int ringbuffer_head; +static unsigned int ringbuffer_head; -static void addToLogbuffer(const char *data, int len) +static void addToLogbuffer(const char *data, unsigned int len) { while (len) { - int remaining = RINGBUFFER_SIZE - ringbuffer_head; - + unsigned int remaining = RINGBUFFER_SIZE - ringbuffer_head; + if (remaining > len) remaining = len; - + memcpy(ringbuffer + ringbuffer_head, data, remaining); len -= remaining; data += remaining; ringbuffer_head += remaining; - if (ringbuffer_head >= RINGBUFFER_SIZE) + ASSERT(ringbuffer_head <= RINGBUFFER_SIZE); + if (ringbuffer_head == RINGBUFFER_SIZE) ringbuffer_head = 0; } } -static std::string getLogBuffer() +static const std::string getLogBuffer() { - int begin = ringbuffer_head; + unsigned int begin = ringbuffer_head; while (ringbuffer[begin] == 0) { ++begin; @@ -48,12 +54,11 @@ static std::string getLogBuffer() if (begin == ringbuffer_head) return ""; } + if (begin < ringbuffer_head) return std::string(ringbuffer + begin, ringbuffer_head - begin); else - { return std::string(ringbuffer + begin, RINGBUFFER_SIZE - begin) + std::string(ringbuffer, ringbuffer_head); - } } static void addToLogbuffer(int level, const std::string &log) @@ -61,117 +66,67 @@ static void addToLogbuffer(int level, const std::string &log) addToLogbuffer(log.c_str(), log.size()); } -static std::string getConfigFileValue(const char *entry) +static const std::string getConfigString(const std::string &key, const std::string &defaultValue) { - std::string configfile = eEnv::resolve("${sysconfdir}/enigma2/settings"); - std::string configvalue; - if (entry) - { - ePythonConfigQuery::getConfigValue(entry, configvalue); - if (configvalue != "") //we get at least the default value if python is still alive - { - return configvalue; - } - else // get value from enigma2 settings file - { - FILE *f = fopen(configfile.c_str(), "r"); - if (!f) - { - return "Error"; - } - while (1) - { - char line[1024]; - if (!fgets(line, 1024, f)) - break; - if (!strncmp(line, entry, strlen(entry) )) - { - if (strlen(line) && line[strlen(line)-1] == '\r') - line[strlen(line)-1] = 0; - if (strlen(line) && line[strlen(line)-1] == '\n') - line[strlen(line)-1] = 0; - std::string tmp = line; - int posEqual = tmp.find("=", 0); - configvalue = tmp.substr(posEqual+1); - } - } - fclose(f); - return configvalue; - } - } -} + std::string value; -static std::string getFileContent(const char *file) -{ - std::string filecontent; + ePythonConfigQuery::getConfigValue(key.c_str(), value); + //we get at least the default value if python is still alive + if (!value.empty()) + return value; - if (file) - { - FILE *f = fopen(file, "r"); - if (!f) - { - return "Error"; - } - while (1) - { - char line[1024]; - if (!fgets(line, 1024, f)) + value = defaultValue; + + // get value from enigma2 settings file + std::ifstream in(eEnv::resolve("${sysconfdir}/enigma2/settings").c_str()); + if (in.good()) { + do { + std::string line; + std::getline(in, line); + size_t size = key.size(); + if (!key.compare(0, size, line) && line[size] == '=') { + value = line.substr(size + 1); break; - std::string tmp = line; - std::string password; - int pwdpos = tmp.find(".password=", 0); - if( pwdpos != std::string::npos) - { - filecontent += tmp.substr(0,pwdpos +10); - for ( int pos = pwdpos +10; pos < tmp.length()-1; ++pos ) - { - filecontent += "X"; - } - filecontent += "\n"; - } - else { - filecontent += line; } - } - fclose(f); + } while (in.good()); + in.close(); } - return filecontent; -} -static std::string execCommand(std::string cmd) { - FILE* pipe = popen(cmd.c_str(), "r"); - if (!pipe) - return "Error"; - char buffer[STDBUFFER_SIZE]; - std::string result = ""; - while(!feof(pipe)) - { - if(!fgets(buffer,STDBUFFER_SIZE, pipe)) - break; - result += buffer; - } - pclose(pipe); - return result; + return value; } -#define INFOFILE "/maintainer.info" +static bool getConfigBool(const std::string &key, bool defaultValue) +{ + std::string value = getConfigString(key, defaultValue ? "true" : "false"); + const char *cvalue = value.c_str(); + + if (!strcasecmp(cvalue, "true")) + return true; + if (!strcasecmp(cvalue, "false")) + return false; + + return defaultValue; +} void bsodFatal(const char *component) { - char logfile[128]; - sprintf(logfile, "/media/hdd/enigma2_crash_%u.log", (unsigned int)time(0)); - FILE *f = fopen(logfile, "wb"); + std::ostringstream os; + os << time(0); + + std::string logfile("/media/hdd/enigma2_crash_" + os.str() + ".log"); + + FILE *f = fopen(logfile.c_str(), "wb"); std::string lines = getLogBuffer(); /* find python-tracebacks, and extract " File "-strings */ size_t start = 0; - char crash_emailaddr[256] = CRASH_EMAILADDR; - char crash_component[256] = "enigma2"; + std::string crash_emailaddr = CRASH_EMAILADDR; + std::string crash_component = "enigma2"; if (component) - snprintf(crash_component, 256, component); + crash_component = component; else { while ((start = lines.find("\n File \"", start)) != std::string::npos) @@ -188,21 +143,12 @@ void bsodFatal(const char *component) if (end == std::string::npos) break; - if (end - start >= (256 - strlen(INFOFILE))) - continue; - char filename[256]; - snprintf(filename, 256, "%s%s", lines.substr(start, end - start).c_str(), INFOFILE); - FILE *cf = fopen(filename, "r"); - if (cf) - { - fgets(crash_emailaddr, sizeof crash_emailaddr, cf); - if (*crash_emailaddr && crash_emailaddr[strlen(crash_emailaddr)-1] == '\n') - crash_emailaddr[strlen(crash_emailaddr)-1] = 0; - - fgets(crash_component, sizeof crash_component, cf); - if (*crash_component && crash_component[strlen(crash_component)-1] == '\n') - crash_component[strlen(crash_component)-1] = 0; - fclose(cf); + + std::string filename(lines.substr(start, end - start) + INFOFILE); + std::ifstream in(filename.c_str()); + if (in.good()) { + std::getline(in, crash_emailaddr) && std::getline(in, crash_component); + in.close(); } } } @@ -210,202 +156,108 @@ void bsodFatal(const char *component) if (f) { time_t t = time(0); - char crashtime[STDBUFFER_SIZE]; - sprintf(crashtime, "%s",ctime(&t)); - if (strlen(crashtime) && crashtime[strlen(crashtime)-1] == '\n') - crashtime[strlen(crashtime)-1] = 0; - fprintf(f, "\n\n"); - fprintf(f, "\t\n"); - fprintf(f, "\t\t%s\n", crashtime); -#ifdef ENIGMA2_CHECKOUT_TAG - fprintf(f, "\t\t" ENIGMA2_CHECKOUT_TAG "\n"); -#else - fprintf(f, "\t\t" __DATE__ "\n"); -#endif -#ifdef ENIGMA2_CHECKOUT_ROOT - fprintf(f, "\t\t" ENIGMA2_CHECKOUT_ROOT "\n"); -#endif - fprintf(f, "\t\t%s\n", crash_emailaddr); - fprintf(f, "\t\t\n"); - std::string activeSkin = getConfigFileValue("config.skin.primary_skin"); - if (activeSkin != "Error") - { - if (activeSkin == "") - activeSkin = "Default Skin"; - fprintf(f, "\t\t%s\n", activeSkin.c_str()); - } - fprintf(f, "\t\n"); + struct tm tm; + char tm_str[32]; - fprintf(f, "\t\n"); - std::string model = getFileContent("/proc/stb/info/model"); - if (model != "Error") - { - char modelname[STDBUFFER_SIZE]; - sprintf(modelname, "%s",model.c_str()); - if (strlen(modelname) && modelname[strlen(modelname)-1] == '\n') - modelname[strlen(modelname)-1] = 0; - fprintf(f, "\t\t%s\n", modelname); - } - std::string kernel = getFileContent("/proc/cmdline"); - if (kernel != "Error") - { - char kernelcmd[STDBUFFER_SIZE]; - sprintf(kernelcmd, "%s",kernel.c_str()); - if (strlen(kernelcmd) && kernelcmd[strlen(kernelcmd)-1] == '\n') - kernelcmd[strlen(kernelcmd)-1] = 0; - fprintf(f, "\t\t%s\n", kernelcmd); - } - std::string sendAnonCrashlog = getConfigFileValue("config.plugins.crashlogautosubmit.sendAnonCrashlog"); - if (sendAnonCrashlog == "False" || sendAnonCrashlog == "false") // defaults to true... default anonymized crashlogs - { - std::string ca = getFileContent("/proc/stb/info/ca"); - if (ca != "Error") - { - char dreamboxca[STDBUFFER_SIZE]; - sprintf(dreamboxca, "%s",ca.c_str()); - if (strlen(dreamboxca) && dreamboxca[strlen(dreamboxca)-1] == '\n') - dreamboxca[strlen(dreamboxca)-1] = 0; - fprintf(f, "\t\t\n\t\t\n\t\t\n", dreamboxca); - } - std::string settings = getFileContent(eEnv::resolve("${sysconfdir}/enigma2/settings").c_str()); - if (settings != "Error") - { - fprintf(f, "\t\t\n\t\t\n\t\t\n", settings.c_str()); - } - } - std::string addNetwork = getConfigFileValue("config.plugins.crashlogautosubmit.addNetwork"); - if (addNetwork == "True" || addNetwork == "true") - { - std::string nwinterfaces = getFileContent("/etc/network/interfaces"); - if (nwinterfaces != "Error") - { - fprintf(f, "\t\t\n\t\t\n\t\t\n", nwinterfaces.c_str()); - } - std::string dns = getFileContent("/etc/resolv.conf"); - if (dns != "Error") - { - fprintf(f, "\t\t\n\t\t\n\t\t\n", dns.c_str()); - } - std::string defaultgw = getFileContent("/etc/default_gw"); - if (defaultgw != "Error") - { - char gateway[STDBUFFER_SIZE]; - sprintf(gateway, "%s",defaultgw.c_str()); - if (strlen(gateway) && gateway[strlen(gateway)-1] == '\n') - gateway[strlen(gateway)-1] = 0; - fprintf(f, "\t\t\n\t\t\n\t\t\n", gateway); - } - } - std::string addWlan = getConfigFileValue("config.plugins.crashlogautosubmit.addWlan"); - if (addWlan == "True" || addWlan == "true") - { - std::string wpasupplicant = getFileContent("/etc/wpa_supplicant.conf"); - if (wpasupplicant != "Error") - { - fprintf(f, "\t\t\n\t\t\n\t\t\n", wpasupplicant.c_str()); - } - } - std::string imageversion = getFileContent("/etc/image-version"); - if (imageversion != "Error") - { - fprintf(f, "\t\t\n\t\t\n\t\t\n", imageversion.c_str()); + localtime_r(&t, &tm); + strftime(tm_str, sizeof(tm_str), "%a %b %_d %T %Y", &tm); + + XmlGenerator xml(f); + + xml.open("opendreambox"); + + xml.open("enigma2"); + xml.string("crashdate", tm_str); + xml.string("compiledate", __DATE__); + xml.string("contactemail", crash_emailaddr); + xml.comment("Please email this crashlog to above address"); + + xml.string("skin", getConfigString("config.skin.primary_skin", "Default Skin")); + xml.string("sourcedate", enigma2_date); + xml.string("branch", enigma2_branch); + xml.string("rev", enigma2_rev); + xml.string("version", PACKAGE_VERSION); + xml.close(); + + xml.open("image"); + xml.stringFromFile("dreamboxmodel", "/proc/stb/info/model"); + xml.stringFromFile("kernelcmdline", "/proc/cmdline"); + if (!getConfigBool("config.plugins.crashlogautosubmit.sendAnonCrashlog", true)) { + xml.cDataFromFile("dreamboxca", "/proc/stb/info/ca"); + xml.cDataFromFile("enigma2settings", eEnv::resolve("${sysconfdir}/enigma2/settings"), ".password="); } - std::string imageissue = getFileContent("/etc/issue.net"); - if (imageissue != "Error") - { - fprintf(f, "\t\t\n\t\t\n\t\t\n", imageissue.c_str()); + if (getConfigBool("config.plugins.crashlogautosubmit.addNetwork", false)) { + xml.cDataFromFile("networkinterfaces", "/etc/network/interfaces"); + xml.cDataFromFile("dns", "/etc/resolv.conf"); + xml.cDataFromFile("defaultgateway", "/etc/default_gw"); } - fprintf(f, "\t\n"); - - fprintf(f, "\t\n"); - std::string installedplugins = execCommand("ipkg list_installed | grep enigma2"); - fprintf(f, "\t\t\n\t\t\n\t\t\n", installedplugins.c_str()); - std::string dreambox = execCommand("ipkg list_installed | grep dream"); - fprintf(f, "\t\t\n\t\t\n\t\t\n", dreambox.c_str()); - std::string gstreamer = execCommand("ipkg list_installed | grep gst"); - fprintf(f, "\t\t\n\t\t\n\t\t\n", gstreamer.c_str()); - fprintf(f, "\t\n"); - - fprintf(f, "\t\n"); - std::string buffer = getLogBuffer(); - fprintf(f, "\t\t\n\t\t\n\t\t\n", buffer.c_str()); - std::string pythonmd5 = execCommand("find " + eEnv::resolve("${libdir}/enigma2/python/") + " -name \"*.py\" | xargs md5sum"); - fprintf(f, "\t\t\n\t\t\n\t\t\n", pythonmd5.c_str()); - fprintf(f, "\t\n"); - - fprintf(f, "\n\n"); + if (getConfigBool("config.plugins.crashlogautosubmit.addWlan", false)) + xml.cDataFromFile("wpasupplicant", "/etc/wpa_supplicant.conf"); + xml.cDataFromFile("imageversion", "/etc/image-version"); + xml.cDataFromFile("imageissue", "/etc/issue.net"); + xml.close(); + + xml.open("software"); + xml.cDataFromCmd("enigma2software", "ipkg list_installed | grep enigma2"); + xml.cDataFromCmd("dreamboxsoftware", "ipkg list_installed | grep dream"); + xml.cDataFromCmd("gstreamersoftware", "ipkg list_installed | grep gst"); + xml.close(); + + xml.open("crashlogs"); + xml.cDataFromString("enigma2crashlog", getLogBuffer()); + xml.cDataFromCmd("pythonMD5sum", "find " + eEnv::resolve("${libdir}/enigma2/python/") + " -name \"*.py\" | xargs md5sum"); + xml.close(); + + xml.close(); + fclose(f); - } - + ePtr my_dc; gMainDC::getInstance(my_dc); - { - gPainter p(my_dc); - p.resetOffset(); - p.resetClip(eRect(ePoint(0, 0), my_dc->size())); -#ifdef ENIGMA2_CHECKOUT_TAG - if (ENIGMA2_CHECKOUT_TAG[0] == 'T') /* tagged checkout (release) */ - p.setBackgroundColor(gRGB(0x0000C0)); - else if (ENIGMA2_CHECKOUT_TAG[0] == 'D') /* dated checkout (daily experimental build) */ - { - srand(time(0)); - int r = rand(); - unsigned int col = 0; - if (r & 1) - col |= 0x800000; - if (r & 2) - col |= 0x008000; - if (r & 4) - col |= 0x0000c0; - p.setBackgroundColor(gRGB(col)); - } -#else - p.setBackgroundColor(gRGB(0x008000)); -#endif + gPainter p(my_dc); + p.resetOffset(); + p.resetClip(eRect(ePoint(0, 0), my_dc->size())); + p.setBackgroundColor(gRGB(0x008000)); + p.setForegroundColor(gRGB(0xFFFFFF)); - p.setForegroundColor(gRGB(0xFFFFFF)); - - ePtr font = new gFont("Regular", 20); - p.setFont(font); - p.clear(); - - eRect usable_area = eRect(100, 70, my_dc->size().width() - 150, 100); - - char text[512]; - snprintf(text, 512, "We are really sorry. Your Dreambox encountered " - "a software problem, and needs to be restarted. " - "Please send the logfile created in /hdd/ to %s.\n" - "Your Dreambox restarts in 10 seconds!\n" - "Component: %s", - crash_emailaddr, crash_component); - - p.renderText(usable_area, text, gPainter::RT_WRAP|gPainter::RT_HALIGN_LEFT); - - usable_area = eRect(100, 170, my_dc->size().width() - 180, my_dc->size().height() - 20); - - int i; + ePtr font = new gFont("Regular", 20); + p.setFont(font); + p.clear(); + + eRect usable_area = eRect(100, 70, my_dc->size().width() - 150, 100); - size_t start = std::string::npos + 1; - for (i=0; i<20; ++i) + std::string text("We are really sorry. Your Dreambox encountered " + "a software problem, and needs to be restarted. " + "Please send the logfile created in /hdd/ to " + crash_emailaddr + ".\n" + "Your Dreambox restarts in 10 seconds!\n" + "Component: " + crash_component); + + p.renderText(usable_area, text.c_str(), gPainter::RT_WRAP|gPainter::RT_HALIGN_LEFT); + + usable_area = eRect(100, 170, my_dc->size().width() - 180, my_dc->size().height() - 20); + + int i; + + start = std::string::npos + 1; + for (i=0; i<20; ++i) + { + start = lines.rfind('\n', start - 1); + if (start == std::string::npos) { - start = lines.rfind('\n', start - 1); - if (start == std::string::npos) - { - start = 0; - break; - } + start = 0; + break; } - - font = new gFont("Regular", 14); - p.setFont(font); - - p.renderText(usable_area, - lines.substr(start), gPainter::RT_HALIGN_LEFT); - sleep(10); } + font = new gFont("Regular", 14); + p.setFont(font); + + p.renderText(usable_area, + lines.substr(start), gPainter::RT_HALIGN_LEFT); + sleep(10); + raise(SIGKILL); } @@ -432,16 +284,13 @@ void oops(const mcontext_t &context, int dumpcode) eDebug(" (end)"); } } -#else -#warning "no oops support!" -#define NO_OOPS_SUPPORT #endif void handleFatalSignal(int signum, siginfo_t *si, void *ctx) { +#ifndef NO_OOPS_SUPPORT ucontext_t *uc = (ucontext_t*)ctx; -#ifndef NO_OOPS_SUPPORT oops(uc->uc_mcontext, signum == SIGSEGV || signum == SIGABRT); #endif eDebug("-------"); diff --git a/main/enigma.cpp b/main/enigma.cpp index 3ea4afb..6bc3571 100644 --- a/main/enigma.cpp +++ b/main/enigma.cpp @@ -28,6 +28,7 @@ #include #include "bsod.h" +#include "version_info.h" #include @@ -296,22 +297,10 @@ void quitMainloop(int exitCode) eApp->quit(0); } -#include "version.h" - const char *getEnigmaVersionString() { - std::string date = -#ifdef ENIGMA2_LAST_CHANGE_DATE - ENIGMA2_LAST_CHANGE_DATE; -#else - __DATE__; -#endif - std::string branch = -#ifdef ENIGMA2_BRANCH - ENIGMA2_BRANCH; -#else - "HEAD"; -#endif + std::string date = enigma2_date; + std::string branch = enigma2_branch; return std::string(date + '-' + branch).c_str(); } diff --git a/main/version_info.cpp b/main/version_info.cpp new file mode 100644 index 0000000..372101d --- /dev/null +++ b/main/version_info.cpp @@ -0,0 +1,18 @@ +#include "version_info.h" +#include "version.h" + +#ifndef ENIGMA2_LAST_CHANGE_DATE +#define ENIGMA2_LAST_CHANGE_DATE __DATE__ +#endif +const char *enigma2_date = ENIGMA2_LAST_CHANGE_DATE; + +#ifndef ENIGMA2_BRANCH +#define ENIGMA2_BRANCH "HEAD" +#endif +const char *enigma2_branch = ENIGMA2_BRANCH; + +#ifndef ENIGMA2_REV +#define ENIGMA2_REV NULL +#endif +const char *enigma2_rev = ENIGMA2_REV; + diff --git a/main/version_info.h b/main/version_info.h new file mode 100644 index 0000000..f93cf01 --- /dev/null +++ b/main/version_info.h @@ -0,0 +1,8 @@ +#ifndef __main_version_info_h__ +#define __main_version_info_h__ + +extern const char *enigma2_date; +extern const char *enigma2_branch; +extern const char *enigma2_rev; + +#endif diff --git a/main/xmlgenerator.cpp b/main/xmlgenerator.cpp new file mode 100644 index 0000000..eb4f157 --- /dev/null +++ b/main/xmlgenerator.cpp @@ -0,0 +1,188 @@ +#include +#include +#include "xmlgenerator.h" + +XmlGenerator::XmlGenerator(FILE *f) : m_file(f), m_indent(true), m_level(0) +{ + ::fprintf(m_file, "\n"); +} + +XmlGenerator::~XmlGenerator() +{ +} + +void XmlGenerator::vprint(const char *fmt, va_list ap, bool newline) +{ + unsigned int i; + + if (m_indent) + for (i = 0; i < m_level; i++) + ::fprintf(m_file, "\t"); + + ::vfprintf(m_file, fmt, ap); + + if (newline) + ::fprintf(m_file, "\n"); +} + +void XmlGenerator::print(const char *fmt, ...) +{ + va_list ap; + + ::va_start(ap, fmt); + vprint(fmt, ap, false); + ::va_end(ap); +} + +void XmlGenerator::printLn(const char *fmt, ...) +{ + va_list ap; + + ::va_start(ap, fmt); + vprint(fmt, ap, true); + ::va_end(ap); +} + +void XmlGenerator::open(const std::string &tag, bool newline) +{ + if (newline) { + printLn("<%s>", tag.c_str()); + } else { + print("<%s>", tag.c_str()); + m_indent = false; + } + + m_tags.push(tag); + m_level++; +} + +void XmlGenerator::open(const std::string &tag) +{ + open(tag, true); +} + +void XmlGenerator::close() +{ + ASSERT(!m_tags.empty()); + ASSERT(m_level > 0); + m_level--; + + printLn("", m_tags.top().c_str()); + m_indent = true; + + m_tags.pop(); +} + +void XmlGenerator::comment(const std::string &str) +{ + printLn("", str.c_str()); +} + +void XmlGenerator::commentFromErrno(const std::string &tag) +{ + open(tag); + comment(strerror(errno)); + close(); +} + +std::string XmlGenerator::cDataEscape(const std::string &str) +{ + const std::string search = "]]>"; + const std::string replace = "]]]]>"; + std::string ret; + size_t pos = 0, opos; + + for (;;) { + opos = pos; + pos = str.find(search, opos); + if (pos == std::string::npos) + break; + ret.append(str, opos, pos - opos); + ret.append(replace); + pos += search.size(); + } + + ret.append(str, opos, std::string::npos); + return ret; +} + +void XmlGenerator::cDataFromCmd(const std::string &tag, const std::string &cmd) +{ + FILE *pipe = ::popen(cmd.c_str(), "re"); + + if (pipe == 0) { + commentFromErrno(tag); + return; + } + + std::string result; + char *lineptr = NULL; + size_t n = 0; + + for (;;) { + ssize_t ret = ::getline(&lineptr, &n, pipe); + if (ret < 0) + break; + result.append(lineptr, ret); + } + + if (lineptr) + ::free(lineptr); + + ::pclose(pipe); + cDataFromString(tag, result); +} + +void XmlGenerator::cDataFromFile(const std::string &tag, const std::string &filename, const char *filter) +{ + std::ifstream in(filename.c_str()); + std::string line; + std::string content; + + if (!in.good()) { + commentFromErrno(tag); + return; + } + + while (std::getline(in, line)) + if (!filter || !line.find(filter)) + content += line + '\n'; + + in.close(); + cDataFromString(tag, content); +} + +void XmlGenerator::cDataFromString(const std::string &tag, const std::string &str) +{ + bool indent = false; + + open(tag); + printLn(""); + std::swap(m_indent, indent); + close(); +} + +void XmlGenerator::string(const std::string &tag, const std::string &str) +{ + open(tag, false); + print("%s", str.c_str()); + close(); +} + +void XmlGenerator::stringFromFile(const std::string &tag, const std::string &filename) +{ + std::ifstream in(filename.c_str()); + std::string line; + + if (!in.good()) { + commentFromErrno(tag); + return; + } + + std::getline(in, line); + in.close(); + string(tag, line); +} diff --git a/main/xmlgenerator.h b/main/xmlgenerator.h new file mode 100644 index 0000000..0dbb262 --- /dev/null +++ b/main/xmlgenerator.h @@ -0,0 +1,43 @@ +#ifndef _main_xmlgenerator_h__ +#define _main_xmlgenerator_h__ + +#include +#include +#include +#include + +class XmlGenerator +{ +private: + FILE *m_file; + bool m_indent; + unsigned int m_level; + std::stack m_tags; + + void vprint(const char *fmt, va_list ap, bool newline); + void __attribute__ ((__format__(__printf__, 2, 3))) print(const char *fmt, ...); + void __attribute__ ((__format__(__printf__, 2, 3))) printLn(const char *fmt, ...); + + void open(const std::string &tag, bool newline); + void commentFromErrno(const std::string &tag); + + std::string cDataEscape(const std::string &str); + +public: + XmlGenerator(FILE *f); + ~XmlGenerator(); + + void open(const std::string &tag); + void close(); + + void comment(const std::string &str); + + void cDataFromCmd(const std::string &tag, const std::string &cmd); + void cDataFromFile(const std::string &tag, const std::string &filename, const char *filter = 0); + void cDataFromString(const std::string &tag, const std::string &str); + + void string(const std::string &tag, const std::string &str); + void stringFromFile(const std::string &tag, const std::string &filename); +}; + +#endif