1
/* ---------------------------------------------------------------------
2
* main(): vk_logmerge program entry point vklm_main.cpp
3
* ---------------------------------------------------------------------
4
* This file is part of Valkyrie, a front-end for Valgrind
5
* Copyright (C) 2000-2008, OpenWorks LLP <info@open-works.co.uk>
6
* This program is released under the terms of the GNU GPL v.2
7
* See the file COPYING for the full license details.
10
#include <sys/types.h> // getpid
11
#include <unistd.h> // getpid
12
#include <stdlib.h> // abort
14
#include <qfileinfo.h>
17
#include <qstringlist.h>
20
#include "vklm_main.h"
21
#include "vglogreader.h"
27
const char* progname=0;
30
#define SKIP_FILE_ON_ERROR 0 /* 0: die, 1: skip */
33
/* print message to stderr */
34
void vklmPrint( int verb, const char* msg, ... )
36
if (vklm_verbosity < verb)
41
fprintf( stderr, "===%s:%d=== ", progname, (int)getpid() );
42
vfprintf( stderr, msg, ap );
44
fprintf( stderr, "\n" );
47
/* print message to stderr */
48
void vklmPrintErr( const char* msg, ... )
53
fprintf( stderr, "===%s:%d=== Error: ", progname, (int)getpid() );
54
vfprintf( stderr, msg, ap );
56
fprintf( stderr, "\n" );
62
fprintf(stderr, "%s, a Valgrind XML log file merger. Version 1.1.0, 27-Nov-2005.\n\n", progname);
64
fprintf(stderr, " usage: %s [flags and input files in any order]\n\n", progname);
66
fprintf(stderr, " -h print this message\n");
67
fprintf(stderr, " -v be verbose (more -v's give more)\n");
68
fprintf(stderr, " -t output plain text (non-xml)\n");
69
fprintf(stderr, " -f log_list obtain input files from log_list (one per line)\n");
70
fprintf(stderr, " -o outfile write merged output to outfile\n\n");
72
fprintf(stderr, " At least 1 input file must be given.\n\n");
74
fprintf(stderr, " If no '-o outfile' is given, writes to standard output.\n\n");
76
fprintf(stderr, " Example: %s log1.xml -f loglist.fls -o merged.xml\n\n", progname);
81
Parse a valgrind xml log file to a VgLog
83
bool parseLog( QString file_path, VgLog& vgLog )
85
#if 1 // TODO: validate file
86
QFile file( file_path );
87
if ( !file.open( IO_ReadOnly ) ) {
88
vklmPrint( 0, "error opening file: '%s'", file_path.latin1() );
94
VgLogReader reader( &vgLog );
95
bool ok = reader.parse( file_path );
97
VgLogHandler* hnd = reader.handler();
98
vklmPrint( 0, "error parsing file '%s'", file_path.latin1() );
99
vklmPrint( 0, " - %s", hnd->fatalMsg().latin1() );
108
Merge all valid Valgrind logs in log_files to master_log
110
bool mergeVgLogList( QStringList& log_files,
111
VgLog& master_log/*out*/ )
113
/* check there's a minimum of one file */
114
if ( log_files.count() < 1 ) {
115
vklmPrint( 0, "No input files specified. For help, try -h." );
119
vklmPrint( 1, "merging logs..." );
121
QString master_fname;
122
unsigned int lognum=0;
124
#if SKIP_FILE_ON_ERROR
125
/* read first parseable file into master */
126
for (lognum=0; lognum<log_files.count(); lognum++) {
127
/* get simple filename */
128
master_fname = QFileInfo( log_files[0] ).fileName();
130
if ( parseLog( log_files[lognum], master_log ) )
132
vklmPrint( 0, "skipping file: '%s'", master_fname.latin1() );
135
#else // DIE_ON_ERROR
136
/* read first file into master */
137
master_fname = QFileInfo( log_files[0] ).fileName();
138
if ( ! parseLog( log_files[0], master_log ) ) {
139
vklmPrint( 0, "failed to parse file: '%s'", master_fname.latin1() );
147
if (lognum >= log_files.count()) {
148
vklmPrint( 1, "no logs to merge" );
152
/* loop over the rest of the files in the list, and merge one-by-one */
153
for (; lognum<log_files.count(); lognum++) {
154
/* get simple filename */
155
QString slave_fname = QFileInfo( log_files[lognum] ).fileName();
158
// TODO: give DTD to use
159
// VgLog slave_log( "valgrind" );
161
bool ok = parseLog( log_files[lognum], slave_log );
162
if (!ok) { /* failed parse/merge of slave file => skipped file */
163
#if SKIP_FILE_ON_ERROR
164
vklmPrint( 0, "skipping file: '%s'", slave_fname.latin1() );
167
#else // DIE_ON_ERROR
168
vklmPrint( 0, "failed to parse file: '%s'", slave_fname.latin1() );
174
vklmPrint( 2, "***********************************************");
175
vklmPrint( 1, "merging %s <- %s", master_fname.latin1(), slave_fname.latin1() );
177
/* --- merge the logs --- */
178
ok = master_log.merge( slave_log );
180
if (!ok) { /* failed parse/merge of slave file => skipped file */
181
#if SKIP_FILE_ON_ERROR
182
vklmPrint( 0, "skipping file: '%s'", slave_fname.latin1() );
185
#else // DIE_ON_ERROR
186
vklmPrint( 0, "merge failed for file: '%s'", slave_fname.latin1() );
192
vklmPrint( 1, "done." );
203
int main ( int argc, char* argv[] )
206
QStringList log_files;
207
bool plaintext_output = false;
209
QString fname_nopath = QFileInfo(argv[0]).fileName();
210
progname = fname_nopath.latin1();
213
parse command-line args
216
while ((c = getopt (argc, argv, "-hvtf:o:")) != -1) {
222
case 'v': /* be verbose */
226
case 1: /* the '-' in optstring puts non-option args here */
227
log_files << optarg; /* we validate the file later */
231
QFile loglist( optarg );
232
if ( !loglist.open( IO_ReadOnly ) ) {
233
vklmPrint( 0, "unable to open logfile '%s'.", optarg );
237
/* add each logfile in loglist to our list */
238
QTextStream stream( &loglist );
239
while ( !stream.atEnd() ) {
240
QString logfile = stream.readLine().simplifyWhiteSpace();
241
if ( logfile.isEmpty() ) /* skip empty lines */
243
log_files << logfile; /* validate the file later. */
254
plaintext_output = true;
268
VgLog mergedLog; // TODO: give DTD: VgLog( "valgrind" );
269
if ( ! mergeVgLogList( log_files, mergedLog ) ) {
270
vklmPrint( 0, "quitting..." );
278
if (plaintext_output)
279
output_str = mergedLog.toPlainTxt();
281
output_str = mergedLog.toString();
283
if ( ! outfile.isEmpty() ) {
285
QFile outFile( outfile );
286
if ( !outFile.open( IO_WriteOnly ) ) {
287
vklmPrint( 0, "error: unable to open file for writing: '%s'",
289
vklmPrint( 0, "failed to save merge result\n" );
293
QTextStream outStream( &outFile );
294
outStream << output_str;
296
vklmPrint( 1, "output saved to '%s'\n", outfile.latin1() );
299
/* write to stdout */
300
fprintf( stdout, "%s", output_str.latin1() );