📄 vglogview.cpp
字号:
/* --------------------------------------------------------------------- * Implementation of VgLogView vglogview.cpp * Links VgLog elements with qlistview elements * --------------------------------------------------------------------- * This file is part of Valkyrie, a front-end for Valgrind * Copyright (c) 2000-2006, OpenWorks LLP <info@open-works.co.uk> * This program is released under the terms of the GNU GPL v.2 * See the file LICENSE.GPL for the full license details. */#include "vglogview.h"#include "vk_utils.h" /* VK_DEBUG */#include "vglogview_icons.h"#include <qfileinfo.h>#include <qstringlist.h>/**********************************************************************//* setup static class maps*/ErrorItem::AcronymMap setupErrAcronymMap() { ErrorItem::AcronymMap amap; amap["CoreMemError"] = "CRM"; amap["InvalidFree"] = "IVF"; amap["MismatchedFree"] = "MMF"; amap["InvalidRead"] = "IVR"; amap["InvalidWrite"] = "IVW"; amap["InvalidJump"] = "IVJ"; amap["Overlap"] = "OVL"; amap["InvalidMemPool"] = "IMP"; amap["UninitCondition"] = "UNC"; amap["UninitValue"] = "UNV"; amap["SyscallParam"] = "SCP"; amap["ClientCheck"] = "CCK"; amap["Leak_DefinitelyLost"] = "LDL"; amap["Leak_IndirectlyLost"] = "LIL"; amap["Leak_PossiblyLost"] = "LPL"; amap["Leak_StillReachable"] = "LSR"; return amap;}ErrorItem::AcronymMap ErrorItem::acronymMap = setupErrAcronymMap();/* base class for SrcItem and OutputItem ------------------------------- */VgOutputItem::VgOutputItem( QListView* parent, VgElement el ) : QListViewItem( parent ), elem( el ){ initialise(); }VgOutputItem::VgOutputItem( QListViewItem* parent, VgElement el ) : QListViewItem( parent ), elem( el ){ initialise(); }VgOutputItem::VgOutputItem( QListViewItem* parent, QListViewItem* after, VgElement el ) : QListViewItem( parent, after ), elem( el ){ initialise(); }void VgOutputItem::initialise() { isReadable = isWriteable = false;}void VgOutputItem::setText( QString str ) { QListViewItem::setText( 0, str ); }VgOutputItem* VgOutputItem::firstChild() { return (VgOutputItem*)QListViewItem::firstChild(); }VgOutputItem* VgOutputItem::nextSibling() { return (VgOutputItem*)QListViewItem::nextSibling(); }VgOutputItem* VgOutputItem::parent(){ return (VgOutputItem*)QListViewItem::parent(); }void VgOutputItem::paintCell( QPainter* p, const QColorGroup& cg, int col, int width, int align ) { if ( ! (isReadable || isWriteable ) ) { QListViewItem::paintCell( p, cg, col, width, align ); } else { QColorGroup cgrp( cg ); cgrp.setColor( QColorGroup::Text, Qt::blue ); QListViewItem::paintCell( p, cgrp, col, width, align ); }}void VgOutputItem::setOpen( bool open ) { QListViewItem::setOpen( open ); }/**********************************************************************//* TopStatus: first item in listview as two text lines: status, client exe errcounts(num_errs), leak_errors(num_bytes++, num_blocks++)*/TopStatusItem::TopStatusItem( QListView* parent, VgStatus status, VgElement exe, QString _protocol ) : VgOutputItem( parent, exe ), num_errs(0), num_bytes(0), num_blocks(0), protocol(_protocol){ QString exe_str = QFileInfo( exe.text() ).fileName(); /* store stime for later use by updateStatus() */ stime = status.getFirstElem( "time" ).text(); status_tmplt = QString("Valgrind: %1 '%2'"); status_str = status_tmplt .arg( status.getFirstElem( "state" ).text() ) .arg( exe_str ); /* errors, leaks */ errcounts_tmplt = QString("Errors: %1 Leaked Bytes: %1 in %2 blocks"); QString err_str = errcounts_tmplt .arg( num_errs ) .arg( num_bytes ) .arg( num_blocks ); setText( status_str + "\n" + err_str ); setMultiLinesEnabled( true );}/* finished */void TopStatusItem::updateStatus( VgStatus status ){ QString etime = status.getFirstElem( "time" ).text(); QString time_str; QTextStream time_strm( &time_str, IO_WriteOnly ); int syear, smonth, sday, shours, smins, ssecs, smsecs; int eyear, emonth, eday, ehours, emins, esecs, emsecs; int ret; if (protocol == "1") { // Valgrind < v3.1 outputs standard date-time /* start date/time */ ret = sscanf( stime.ascii(), "%d-%d-%d %d:%d:%d.%4d", &syear, &smonth, &sday, &shours, &smins, &ssecs, &smsecs ); if (ret == 7) { QDate sta_date; QTime sta_time( shours, smins, ssecs, smsecs ); sta_date = QDate( syear, smonth, sday ); time_strm << sta_date.toString( "MMM/d/yy " ); time_strm << sta_time.toString( "hh:mm:ss.zzz" ); /* end date/time */ time_strm << " - "; ret = sscanf( etime.ascii(), "%d-%d-%d %d:%d:%d.%4d", &eyear, &emonth, &eday, &ehours, &emins, &esecs, &emsecs ); if (ret == 7) { /* end date/time */ QDate end_date = QDate( eyear, emonth, eday ); QTime end_time( ehours, emins, esecs, emsecs ); // only output end_date if > start_date if ( end_date > sta_date ) time_strm << end_date.toString( "MMM/d/yy " ); time_strm << end_time.toString( "hh:mm:ss.zzz" ); /* elapsed time */ time_strm << " ("; if ( end_date > sta_date ) { int days = sta_date.daysTo( end_date ); time_strm << days << ((days == 1) ? "day " : "days "); } QTime time_a; /* 00:00:00.000 */ QTime elapsed_time = time_a.addMSecs( sta_time.msecsTo( end_time ) ); time_strm << elapsed_time.toString( "hh:mm:ss.zzz" ) << ")"; } else { VK_DEBUG("can't read end-time string\n"); } } else { VK_DEBUG("can't read start-time string\n"); } } else if (protocol == "2") { // Valgrind >= v3.1 outputs a count only /* start count */ ret = sscanf( stime.ascii(), "%d:%d:%d:%d.%4d", &sday, &shours, &smins, &ssecs, &smsecs ); if (ret == 5) { ret = sscanf( etime.ascii(), "%d:%d:%d:%d.%4d", &eday, &ehours, &emins, &esecs, &emsecs ); if (ret == 5 ) { /* elapsed time */ int msecs = emsecs - smsecs; int secs = esecs - ssecs; int mins = emins - smins; int hours = ehours - shours; int days = eday - sday; if (msecs < 0) { secs--; msecs += 1000; } if (secs < 0) { mins--; secs += 60; } if (mins < 0) { hours--; mins += 60; } if (hours < 0) { days--; hours += 24; } if (days < 0) { VK_DEBUG("negative runtime!\n"); msecs = secs = mins = hours = days = 0; } time_strm << "(wallclock runtime: "; if (days > 0) time_strm << days << ((days == 1) ? "day " : "days " ); if (hours > 0 || days > 0) time_strm << hours << ((hours == 1) ? "hour " : "hours "); if (mins > 0 || hours > 0 || days > 0) time_strm << mins << ((mins == 1) ? "min " : "mins " ); time_strm << secs << "." << msecs << "secs)"; } else { VK_DEBUG("can't read end-time string (protocol 2)\n"); } } else { VK_DEBUG("can't read start-time string\n"); } } else { VK_DEBUG("bad xml protocol version: '%s'\n", protocol.ascii() ); } /* setup the first part: */ status_str = status_tmplt .arg( status.getFirstElem( "state" ).text() ) // FINISHED .arg( QFileInfo( elem.text() ).fileName() ); // exe status_str += " " + time_str; /* errors, leaks */ QString err_str = errcounts_tmplt .arg( num_errs ) .arg( num_bytes ) .arg( num_blocks ); setText( status_str + "\n" + err_str );}void TopStatusItem::updateErrorCounts( VgErrCounts ec ){ /* sum all counts in all pairs of errorcounts */ num_errs = 0; QDomNodeList pairs = ec.childNodes(); QDomElement e = pairs.item(0).toElement(); for (; !e.isNull(); e = e.nextSibling().toElement() ) { VgElement pair = (VgElement&)e; QString count = pair.firstChild().toElement().text(); num_errs += count.toInt(); } QString err_str = errcounts_tmplt .arg( num_errs ) .arg( num_bytes ) .arg( num_blocks ); setText( status_str + "\n" + err_str );}void TopStatusItem::updateLeakCounts( VgError err ){ if ( !err.isLeak() ) return; /* HACK ALERT! VALGRIND_DO_LEAK_CHECK gives repeated leaks... taking apart error::what to get record number - if '1' then reset counters */ QString what = err.getFirstElem("what").text(); QString lr_str = what.mid( what.find( "in loss record " ) ); /* merged logs may not have a 'loss record' string... */ if ( !lr_str.isEmpty() ) { /* valgrind can output multiple leak summaries - reset counts when we get a new summary */ QString record = QStringList::split( " ", lr_str )[3]; if (record == "1") { num_bytes = num_blocks = 0; } } num_bytes += err.getFirstElem("leakedbytes").text().toUInt(); num_blocks += err.getFirstElem("leakedblocks").text().toUInt(); QString err_str = errcounts_tmplt .arg( num_errs ) .arg( num_bytes ) .arg( num_blocks ); setText( status_str + "\n" + err_str );}/**********************************************************************//* InfoItem - info: as text line: tool, pid, ppid - logfilequal - var: as text line - value: as text line - usercomment: - comment: as text line - args - details: as text lines*/InfoItem::InfoItem( VgOutputItem* parent, VgElement root /*element:ROOT*/ ) : VgOutputItem( parent, root ){ QString tool = elem.getFirstElem("tool").text(); tool[0] = tool[0].upper(); QString pid = elem.getFirstElem("pid").text(); QString ppid = elem.getFirstElem("ppid").text(); QString content = QString("%1 output for process id ==%2== (parent pid ==%3==)") .arg( tool ) .arg( pid ) .arg( ppid ); setText( content ); setExpandable( true );}void InfoItem::setOpen( bool open ){ if ( open && childCount() == 0 ) { VgOutputItem* after = 0; VgElement logqual = elem.getFirstElem("logfilequalifier"); /* may / may not have log-file-qualifier */ if ( ! logqual.isNull() ) { after = new LogQualItem( this, logqual ); after->setOpen( true ); } VgElement comment = elem.getFirstElem("usercomment"); /* may / may not have a user comment */ if ( ! comment.isNull() ) { after = new CommentItem( this, after, comment ); after->setOpen( true ); } VgElement args = elem.getFirstElem("args"); /* args */ after = new ArgsItem( this, after, args ); after->setOpen( true ); } VgOutputItem::setOpen( open );}/**********************************************************************//* LogQualItem */LogQualItem::LogQualItem( VgOutputItem* parent, VgElement logqual ) : VgOutputItem( parent, logqual ){ setText( "logfilequalifier" );}void LogQualItem::setOpen( bool open ){ if ( open && childCount() == 0 ) { VgOutputItem* last_item = 0; QDomElement e = elem.firstChild().toElement(); for ( ; !e.isNull(); e = e.nextSibling().toElement() ) { VgElement elem = (VgElement&)e; last_item = new VgOutputItem( this, last_item, elem ); last_item->setText( elem.text() ); } } VgOutputItem::setOpen( open );}/**********************************************************************//* CommentItem */CommentItem::CommentItem( VgOutputItem* parent, QListViewItem* after, VgElement cmnt ) : VgOutputItem( parent, after, cmnt ){ setText( "usercomment" );}void CommentItem::setOpen( bool open ){ if ( open && childCount() == 0 ) { VgOutputItem* item = new VgOutputItem( this, elem ); item->setText( elem.text() ); } VgOutputItem::setOpen( open );}/**********************************************************************//* ArgsItem */ArgsItem::ArgsItem( VgOutputItem* parent, QListViewItem* after, VgElement args ) : VgOutputItem( parent, after, args ){ setText( "args" );}void ArgsItem::setOpen( bool open ){ if ( open && childCount() == 0 ) { VgElement vgInfo = elem.getFirstElem("vargv"); VgElement exInfo = elem.getFirstElem("argv"); VgOutputItem* last_item = 0; QDomElement e = vgInfo.firstChild().toElement();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -