1
/* ----------------------------------------------------------------------
2
* Various utility functions vk_utils.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.
11
#include "config.h" // PACKAGE_BUGREPORT
12
#include "vk_config.h" // vkname()
14
#include <stdlib.h> // mkstemp()
15
#include <stdarg.h> // va_start, va_end
16
#include <sys/types.h> // getpid
17
#include <unistd.h> // getpid
18
#include <pwd.h> // getpwuid
20
#include <qapplication.h>
21
#include <qfileinfo.h>
24
#include <qstringlist.h>
28
/* TODO: add user-opt to output valkyrie messages to different fd... a-la valgrind
29
- keeps stdout/err clean for client program output
33
/* prints various info msgs to stdout --------------------------------- */
34
void vkPrint( const char* msg, ... )
36
const char* vkname = vkConfig ? vkConfig->vkname() : "";
40
fprintf( stdout, "===%s:%d=== ", vkname, (int)getpid() );
41
vfprintf( stdout, msg, ap );
43
fprintf( stdout, "\n" );
48
/* prints error msg -------------------------------------------------- */
49
void vkPrintErr( const char* msg, ... )
51
const char* vkname = vkConfig ? vkConfig->vkname() : "";
55
fprintf( stderr, "===%s:%d=== ", vkname, (int)getpid() );
56
vfprintf( stderr, msg, ap );
58
fprintf( stderr, "\n" );
63
/* Kludge to keep vglog happy
64
- Want vk_logmerge to print progress messages from class VgLog,
65
but keep that class within valkyrie...
66
- Hmm... perhaps shove that class into vk_logmerge after all...
67
TODO: Figure out what we want and implement it!
69
void vklmPrint( int, const char*, ... ) { /* nada */ }
70
void vklmPrintErr( const char* msg, ... )
72
/* same as vkPrintErr()
73
TODO: how to forward call with mult args? */
74
const char* vkname = vkConfig ? vkConfig->vkname() : "";
78
fprintf( stderr, "===%s:%d=== ", vkname, (int)getpid() );
79
vfprintf( stderr, msg, ap );
81
fprintf( stderr, "\n" );
87
/* prints an "Assertion failed" message and exits ---------------------- */
88
__attribute__ ((noreturn))
89
void vk_assert_fail( const char* expr, const char* file,
90
unsigned int line, const char* fn )
92
vkPrintErr("Assertion failed '%s':", expr );
93
vkPrintErr(" at %s#%u:%s\n", file, line, fn );
97
/* prints a message asking user to email a bug report,
98
* and then exits. ----------------------------------------------------- */
99
__attribute__ ((noreturn))
100
void vk_assert_never_reached_fail( const char* file,
104
vkPrintErr("Assertion 'never reached' failed,");
105
vkPrintErr(" at %s#%u:%s", file, line, fn );
106
vkPrintErr("%s version: %s", vkConfig->vkName(), PACKAGE_VERSION);
107
vkPrintErr("Built with QT version: %s", QT_VERSION_STR);
108
vkPrintErr("Running with QT version: %s", qVersion());
109
vkPrintErr("Hopefully, you should never see this message.");
110
vkPrintErr("If you are, then Something Really Bad just happened.");
111
vkPrintErr("Please report this bug to: %s", PACKAGE_BUGREPORT );
112
vkPrintErr("In the bug report, please send the the above text,");
113
vkPrintErr("along with the output of `uname -a`.");
114
vkPrintErr("Thanks.\n");
119
/* Create a unique filename, with an optional extension ---------------- */
120
QString vk_mkstemp( QString filepath, QString ext/*=QString::null*/ )
122
/* create tempfiles with datetime, so can sort easily if they stay around */
124
QString datetime = QDateTime::currentDateTime().toString( "-yyyy.MM.dd-hh.mm.ss");
125
QString unique = filepath + datetime;
126
if (!ext.isNull()) unique += "." + ext;
128
if ( QFile::exists(unique) ) {
129
/* fall back on mkstemp */
130
char* tmpname = vk_str_malloc( unique.length() + 10 );
131
sprintf( tmpname, "%s.XXXXXX", unique.latin1() );
132
int fd = mkstemp( tmpname );
134
/* something went wrong */
135
VK_DEBUG("failed to create unique filename from '%s'.",
137
return QString::null;
139
unique = QString( tmpname );
140
tmpname = vk_str_free( tmpname );
146
/* Get the log directory associated with this user --------------------- */
147
// Just do this once, and cache the results.
148
QString get_VK_LOGS_DIR ()
150
static QString res = NULL;
153
struct passwd* pw = getpwuid( me );
154
/* This should never fail. Is it worth trying to continue if it
155
does? I don't think so. */
157
res = QString( VK_LOGS_DIRP ) + QString( pw->pw_name ) + "/";
164
/* Version check -------------------------------------------------------
165
Given version string of "major.minor.patch" (e.g. 3.3.0),
166
hex version = (major << 16) + (minor << 8) + patch
168
int strVersion2hex( QString ver_str )
170
QRegExp rxver(".*(\\d{1,2})\\.(\\d{1,2})\\.(\\d{1,2}).*");
171
if ( rxver.search( ver_str ) == -1)
173
int major = rxver.cap(1).toInt();
174
int minor = rxver.cap(2).toInt();
175
int patch = rxver.cap(3).toInt();
176
return (major << 16) + (minor << 8) + patch;
181
/* escape html entities
182
current list: '<', '>', '&' ----------------------------------------- */
183
QString escapeEntities( const QString& content )
185
QString ret_str = "";
187
for ( unsigned int i=0; i<content.length(); i++ ) {
188
switch ( content[i].latin1() ) {
189
case '<': ret_str += "<"; break;
190
case '>': ret_str += ">"; break;
192
/* already escaped? */
193
if ((content.mid(i+1,4) == "amp;") ||
194
(content.mid(i+1,3) == "lt;" ) ||
195
(content.mid(i+1,3) == "gt;" ))
196
ret_str += content[i];
200
default: ret_str += content[i]; break;
208
/* swap '\n' for <br> */
209
QString str2html( QString str )
211
str.replace( '\n', "<br>" );
216
/* wrappers for various fns -------------------------------------------- */
218
/* wrappers to free(3)
219
hides const compilation noise, permit NULL, return NULL always. */
220
void * vk_free( const void* ptr )
229
char * vk_str_free( const char* ptr )
237
void * vk_malloc( unsigned long n_bytes )
240
mem = malloc( n_bytes );
242
VK_DEBUG( "failed to allocate %lu bytes", n_bytes );
248
char * vk_str_malloc( int sz )
251
arr = (char*) malloc( (size_t) ((sz + 2)*sizeof(char)) );
253
VK_DEBUG("malloc failure: virtual memory exhausted");
254
vk_assert_never_reached();
260
/* wrapper to strcmp(): returns true || false */
261
bool vk_strcmp( const char* str1, const char* str2 )
263
if ( !str1 || !str2 ) {
264
VK_DEBUG("can't call strcmp on null strings:\n"
265
"str1 == %s, str2 == %s\n", str1, str2 );
268
if ( (strlen(str1) == 0) || (strlen(str2) == 0) ) {
269
VK_DEBUG("one of these two strings is empty:\n"
270
"\tstr1: -->%s<--, str2: -->%s<--\n", str1, str2 );
274
return (strcmp( str1, str2 ) == 0) ? true : false;
278
char* vk_strdup( const char* str )
283
length = strlen( str ) + 1;
284
new_str = vk_str_malloc( length );
285
strcpy( new_str, str );