~ubuntu-branches/ubuntu/oneiric/valkyrie/oneiric

« back to all changes in this revision

Viewing changes to vk_logmerge/vklm_main.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Hai Zaar
  • Date: 2009-05-06 14:48:00 UTC
  • Revision ID: james.westby@ubuntu.com-20090506144800-vw617m4d4qa2pam3
Tags: upstream-1.4.0
ImportĀ upstreamĀ versionĀ 1.4.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.
 
8
 */
 
9
 
 
10
#include <sys/types.h>   // getpid
 
11
#include <unistd.h>      // getpid
 
12
#include <stdlib.h>      // abort
 
13
 
 
14
#include <qfileinfo.h>
 
15
#include <qdom.h>
 
16
#include <qstring.h>
 
17
#include <qstringlist.h>
 
18
#include <qmap.h>
 
19
 
 
20
#include "vklm_main.h"
 
21
#include "vglogreader.h"
 
22
#include "vglog.h"
 
23
 
 
24
 
 
25
 
 
26
/* Global vars */
 
27
const char* progname=0;
 
28
int vklm_verbosity=0;
 
29
 
 
30
#define SKIP_FILE_ON_ERROR 0  /* 0: die, 1: skip */
 
31
 
 
32
 
 
33
/* print message to stderr */
 
34
void vklmPrint( int verb, const char* msg, ... )
 
35
{
 
36
   if (vklm_verbosity < verb)
 
37
      return;
 
38
   va_list ap;
 
39
   va_start( ap, msg );
 
40
   va_end( ap );
 
41
   fprintf( stderr, "===%s:%d=== ", progname, (int)getpid() ); 
 
42
   vfprintf( stderr, msg, ap );
 
43
   va_end( ap );
 
44
   fprintf( stderr, "\n" );
 
45
}
 
46
 
 
47
/* print message to stderr */
 
48
void vklmPrintErr( const char* msg, ... )
 
49
{
 
50
   va_list ap;
 
51
   va_start( ap, msg );
 
52
   va_end( ap );
 
53
   fprintf( stderr, "===%s:%d=== Error: ", progname, (int)getpid() ); 
 
54
   vfprintf( stderr, msg, ap );
 
55
   va_end( ap );
 
56
   fprintf( stderr, "\n" );
 
57
}
 
58
 
 
59
 
 
60
void usage()
 
61
{
 
62
   fprintf(stderr, "%s, a Valgrind XML log file merger.  Version 1.1.0, 27-Nov-2005.\n\n", progname);
 
63
 
 
64
   fprintf(stderr, "  usage: %s [flags and input files in any order]\n\n", progname);
 
65
 
 
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");
 
71
 
 
72
   fprintf(stderr, "  At least 1 input file must be given.\n\n");
 
73
 
 
74
   fprintf(stderr, "  If no '-o outfile' is given, writes to standard output.\n\n");
 
75
 
 
76
   fprintf(stderr, "  Example: %s log1.xml -f loglist.fls -o merged.xml\n\n", progname);
 
77
}
 
78
 
 
79
 
 
80
/*
 
81
  Parse a valgrind xml log file to a VgLog
 
82
*/
 
83
bool parseLog( QString file_path, VgLog& vgLog )
 
84
{
 
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() );
 
89
      return false;
 
90
   }
 
91
   file.close();
 
92
#endif
 
93
 
 
94
   VgLogReader reader( &vgLog );
 
95
   bool ok = reader.parse( file_path );
 
96
   if (!ok) {
 
97
      VgLogHandler* hnd = reader.handler();
 
98
      vklmPrint( 0, "error parsing file '%s'", file_path.latin1() );
 
99
      vklmPrint( 0, " - %s", hnd->fatalMsg().latin1() );
 
100
      return false;
 
101
   }
 
102
 
 
103
   return true;
 
104
}
 
105
 
 
106
 
 
107
/*
 
108
  Merge all valid Valgrind logs in log_files to master_log
 
109
*/
 
110
bool mergeVgLogList( QStringList& log_files, 
 
111
                     VgLog& master_log/*out*/ )
 
112
{
 
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." );
 
116
      return false;
 
117
   }
 
118
 
 
119
   vklmPrint( 1, "merging logs..." );
 
120
 
 
121
   QString master_fname;
 
122
   unsigned int lognum=0;
 
123
 
 
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();
 
129
 
 
130
      if ( parseLog( log_files[lognum], master_log ) )
 
131
         break;
 
132
      vklmPrint( 0, "skipping file: '%s'", master_fname.latin1() );
 
133
      vklmPrint( 0, " " );
 
134
   }
 
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() );
 
140
      vklmPrint( 0, " " );
 
141
      return false;
 
142
   }
 
143
#endif
 
144
 
 
145
   lognum++;
 
146
 
 
147
   if (lognum >= log_files.count()) {
 
148
      vklmPrint( 1, "no logs to merge" );
 
149
      vklmPrint( 1, " " );
 
150
   }
 
151
 
 
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();
 
156
 
 
157
      VgLog slave_log;
 
158
      // TODO: give DTD to use
 
159
      //  VgLog slave_log( "valgrind" );
 
160
 
 
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() );
 
165
         vklmPrint( 0, " " );
 
166
         continue;
 
167
#else // DIE_ON_ERROR
 
168
         vklmPrint( 0, "failed to parse file: '%s'", slave_fname.latin1() );
 
169
         vklmPrint( 0, " " );
 
170
         return false;
 
171
#endif
 
172
      }
 
173
 
 
174
      vklmPrint( 2, "***********************************************");
 
175
      vklmPrint( 1, "merging %s <- %s", master_fname.latin1(), slave_fname.latin1() );
 
176
 
 
177
      /* --- merge the logs --- */
 
178
      ok = master_log.merge( slave_log );
 
179
 
 
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() );
 
183
         vklmPrint( 0, " " );
 
184
         continue;
 
185
#else // DIE_ON_ERROR
 
186
         vklmPrint( 0, "merge failed for file: '%s'", slave_fname.latin1() );
 
187
         vklmPrint( 0, " " );
 
188
         return false;
 
189
#endif
 
190
      }
 
191
   }
 
192
   vklmPrint( 1, "done." );
 
193
 
 
194
   return true;
 
195
}
 
196
 
 
197
 
 
198
 
 
199
 
 
200
/*
 
201
  Main
 
202
*/
 
203
int main ( int argc, char* argv[] )
 
204
{
 
205
   QString outfile;
 
206
   QStringList log_files;
 
207
   bool plaintext_output = false;
 
208
 
 
209
   QString fname_nopath = QFileInfo(argv[0]).fileName();
 
210
   progname = fname_nopath.latin1();
 
211
 
 
212
   /*
 
213
     parse command-line args
 
214
   */
 
215
   int c;
 
216
   while ((c = getopt (argc, argv, "-hvtf:o:")) != -1) {
 
217
      switch (c) {
 
218
      case 'h':  /* help */
 
219
         usage();
 
220
         return 0;
 
221
      
 
222
      case 'v':  /* be verbose */
 
223
         vklm_verbosity++;
 
224
         break;
 
225
      
 
226
      case 1:  /* the '-' in optstring puts non-option args here */
 
227
         log_files << optarg;    /* we validate the file later */
 
228
         break;
 
229
 
 
230
      case 'f': {
 
231
         QFile loglist( optarg );
 
232
         if ( !loglist.open( IO_ReadOnly ) ) {
 
233
            vklmPrint( 0, "unable to open logfile '%s'.", optarg );
 
234
            return 1;
 
235
         }
 
236
 
 
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 */
 
242
               continue;
 
243
            log_files << logfile;      /* validate the file later. */
 
244
         }
 
245
         loglist.close();
 
246
         break;
 
247
      }
 
248
 
 
249
      case 'o':
 
250
         outfile = optarg;
 
251
         break;
 
252
      
 
253
      case 't':
 
254
         plaintext_output = true;
 
255
         break;
 
256
      
 
257
      case '?':
 
258
         usage();
 
259
         return 1;
 
260
      default:
 
261
         abort();
 
262
      }
 
263
   }
 
264
 
 
265
   /*
 
266
     merge
 
267
   */
 
268
   VgLog mergedLog;    // TODO: give DTD: VgLog( "valgrind" );
 
269
   if ( ! mergeVgLogList( log_files, mergedLog ) ) {
 
270
      vklmPrint( 0, "quitting..." );
 
271
      return 1;
 
272
   }
 
273
 
 
274
   /*
 
275
     output result
 
276
   */
 
277
   QString output_str;
 
278
   if (plaintext_output)
 
279
      output_str = mergedLog.toPlainTxt();
 
280
   else
 
281
      output_str = mergedLog.toString();
 
282
 
 
283
   if ( ! outfile.isEmpty() ) {
 
284
      /* write to file */
 
285
      QFile outFile( outfile );
 
286
      if ( !outFile.open( IO_WriteOnly ) ) {
 
287
         vklmPrint( 0, "error: unable to open file for writing: '%s'", 
 
288
                    outfile.latin1() );
 
289
         vklmPrint( 0, "failed to save merge result\n" );
 
290
         return 1;
 
291
      }
 
292
 
 
293
      QTextStream outStream( &outFile );
 
294
      outStream << output_str;
 
295
      outFile.close();
 
296
      vklmPrint( 1, "output saved to '%s'\n", outfile.latin1() );
 
297
 
 
298
   } else {
 
299
      /* write to stdout */
 
300
      fprintf( stdout, "%s", output_str.latin1() );
 
301
   }
 
302
 
 
303
   return 0;
 
304
}
 
305