|
From: <sv...@va...> - 2010-01-08 21:43:57
|
Author: cerion
Date: 2010-01-08 21:43:43 +0000 (Fri, 08 Jan 2010)
New Revision: 464
Log:
Finally, command-line parsing is up and running again. good grief.
Added:
branches/valkyrie_qt4port/options/vk_parse_cmdline.cpp
branches/valkyrie_qt4port/options/vk_parse_cmdline.h
branches/valkyrie_qt4port/options/vk_popt.cpp
branches/valkyrie_qt4port/options/vk_popt.h
Modified:
branches/valkyrie_qt4port/main.cpp
branches/valkyrie_qt4port/objects/valgrind_object.cpp
branches/valkyrie_qt4port/objects/valgrind_object.h
branches/valkyrie_qt4port/objects/valkyrie_object.cpp
branches/valkyrie_qt4port/objects/valkyrie_object.h
branches/valkyrie_qt4port/objects/vk_objects.cpp
branches/valkyrie_qt4port/objects/vk_objects.h
branches/valkyrie_qt4port/options/valgrind_options_page.cpp
branches/valkyrie_qt4port/options/valkyrie_options_page.cpp
branches/valkyrie_qt4port/options/vk_option.cpp
branches/valkyrie_qt4port/options/vk_option.h
branches/valkyrie_qt4port/options/vk_options_page.cpp
branches/valkyrie_qt4port/utils/vk_config.cpp
branches/valkyrie_qt4port/utils/vk_config.h
branches/valkyrie_qt4port/valkyrie.pro
Modified: branches/valkyrie_qt4port/main.cpp
===================================================================
--- branches/valkyrie_qt4port/main.cpp 2010-01-08 09:18:57 UTC (rev 463)
+++ branches/valkyrie_qt4port/main.cpp 2010-01-08 21:43:43 UTC (rev 464)
@@ -26,6 +26,7 @@
#include "mainwindow.h"
#include "utils/vk_config.h"
+#include "options/vk_parse_cmdline.h"
VkConfig* vkConfig = 0;
@@ -39,7 +40,7 @@
*/
int main(int argc, char *argv[])
{
- int res = EXIT_SUCCESS;
+ int exit_status = EXIT_SUCCESS;
QApplication* app = 0;
MainWindow* vkWin = 0;
@@ -69,7 +70,28 @@
cerr << "Error: config not initialised properly: No guarantees from here!" << endl;
}
+
// ------------------------------------------------------------
+ // Command-line parsing
+ // - if a project file is given, the settings will override the initialised vkConfig.
+ if ( argc > 1 ) {
+ // parse cmdline args, overwrite vkConfig with any options found.
+ bool show_help_and_exit;
+ if ( ! parseCmdArgs( argc, argv, &valkyrie, show_help_and_exit ) ) {
+ exit_status = EXIT_FAILURE;
+ goto cleanup_and_exit;
+ }
+ if ( show_help_and_exit ) {
+ goto cleanup_and_exit;
+ }
+ }
+
+ // save the working config
+ vkConfig->sync();
+
+
+
+ // ------------------------------------------------------------
// Start up the gui
vkWin = new MainWindow( &valkyrie );
vkWin->show();
@@ -79,14 +101,15 @@
// ------------------------------------------------------------
// Hand over to QtApp.
- res = app->exec();
+ exit_status = app->exec();
+cleanup_and_exit:
// ------------------------------------------------------------
// We're done - clean up and return.
if ( vkWin ) delete vkWin;
if ( vkConfig ) delete vkConfig;
if ( app ) delete app;
- return res;
+ return exit_status;
}
Modified: branches/valkyrie_qt4port/objects/valgrind_object.cpp
===================================================================
--- branches/valkyrie_qt4port/objects/valgrind_object.cpp 2010-01-08 09:18:57 UTC (rev 463)
+++ branches/valkyrie_qt4port/objects/valgrind_object.cpp 2010-01-08 21:43:43 UTC (rev 464)
@@ -517,8 +517,29 @@
-/* check argval for this option, updating if necessary.
- called by parseCmdArgs() and gui option pages -------------------- */
+
+
+
+/*!
+ Update config - special cases
+*/
+void Valgrind::updateConfig( int optid, QString& argval )
+{
+ // exception: multiple suppressions are allowed
+ if ( optid == VALGRIND::SUPPS_SEL ) {
+//TODO: concat, don't overwrite
+ // vkConfig->value( vk_opt->configKey() );
+ // argval = cfg_argval + argval
+ }
+
+ VkObject::updateConfig( optid, argval );
+}
+
+
+
+/*!
+ Check \a argval for the option given by \a optid, updating if necessary.
+*/
int Valgrind::checkOptArg( int optid, QString& argval )
{
optid = optid; argval = argval;
Modified: branches/valkyrie_qt4port/objects/valgrind_object.h
===================================================================
--- branches/valkyrie_qt4port/objects/valgrind_object.h 2010-01-08 09:18:57 UTC (rev 463)
+++ branches/valkyrie_qt4port/objects/valgrind_object.h 2010-01-08 21:43:43 UTC (rev 464)
@@ -88,6 +88,8 @@
int checkOptArg( int optid, QString& argval );
+ void updateConfig( int optid, QString& argval );
+
VkOptionsPage* createVkOptionsPage();
#if 0
Modified: branches/valkyrie_qt4port/objects/valkyrie_object.cpp
===================================================================
--- branches/valkyrie_qt4port/objects/valkyrie_object.cpp 2010-01-08 09:18:57 UTC (rev 463)
+++ branches/valkyrie_qt4port/objects/valkyrie_object.cpp 2010-01-08 21:43:43 UTC (rev 464)
@@ -23,7 +23,9 @@
#include "utils/vk_config.h"
#include "utils/vk_utils.h"
+#include <QFile>
+
// TODO: put this in a define in the build scripts,or something.
// Minimum version of Valgrind required
const char* pchVersionVgMin = "3.6.0";
@@ -39,7 +41,7 @@
{
setupOptions();
- /* init valgrind */
+ // init valgrind
m_valgrind = new Valgrind();
}
@@ -361,14 +363,74 @@
/*!
- Check \a argval for the option given by \a optid, updating if necessary.
- Called by parseCmdArgs() and gui option pages
+ Check \a argval for the option given by \a optGrp and \a optid.
+ The \a argval may be updated.
*/
+int Valkyrie::checkOptArg( QString optGrp, int optid, QString& argval )
+{
+ VkObjectList objList = this->vkObjList();
+ for (int i = 0; i < objList.size(); ++i) {
+ VkObject* obj = objList.at(i);
+
+ // find the option owner, call checkOptArg for that owner.
+ if ( obj->objectName() == optGrp ) {
+ return obj->checkOptArg( optid, argval );
+ }
+ }
+ return PERROR_BADOPT;
+}
+
+
+
+/*!
+ Update config
+ General access function, when specific object not known
+*/
+void Valkyrie::updateConfig( QString optGrp, int optid, QString& argval )
+{
+ VkObjectList objList = this->vkObjList();
+ for (int i = 0; i < objList.size(); ++i) {
+ VkObject* obj = objList.at(i);
+
+ // find the option owner, call checkOptArg for that owner.
+ if ( obj->objectName() == optGrp ) {
+ return obj->updateConfig( optid, argval );
+ }
+ }
+}
+
+
+
+/*!
+ Update config - special cases
+*/
+void Valkyrie::updateConfig( int optid, QString& argval )
+{
+ // Load config settings from project file
+ // - load these first before
+ if ( optid == VALKYRIE::PROJ_FILE ) {
+ QString proj_filename = argval;
+
+ if ( !QFile::exists( proj_filename ) ) {
+ vkConfig->createNewProject( proj_filename );
+ } else {
+ vkConfig->openProject( proj_filename );
+ }
+ }
+
+ VkObject::updateConfig( optid, argval );
+}
+
+
+
+/*!
+ Check \a argval for the option given by \a optid, updating if necessary.
+*/
int Valkyrie::checkOptArg( int optid, QString& argval )
-{
+{
vk_assert( optid >= 0 && optid < VALKYRIE::NUM_OPTS );
- VkOption* opt = this->options.getOption( optid );
+ VkOption* opt = getOption( optid );
#if 0 // TODO
int errval = PARSED_OK;
@@ -392,7 +454,7 @@
case VALKYRIE::DFLT_LOGDIR:
case VALKYRIE::WORKING_DIR: {
- /* see if we have an dir with rx permissions */
+ // see if we have an dir with rx permissions
(void) dirCheck( &errval, argval, true, true );
} break;
@@ -402,13 +464,31 @@
argval.replace( ed_file, ed );
} break;
+ case VALKYRIE::PROJ_FILE: {
+#if 0 // TODO: review this
+
+ // TODO: check filname format: ( dir + "/" + proj_name + "." + VK_CFG_EXT )
+
+ // TODO: check dir exists & perms ok
+
+ // check owner read/write perms ok
+ if ( QFile::exists( proj_filename ) ) {
+ QFile::Permissions perms = QFile::permissions( proj_filename );
+ if ( ( perms & QFile::WriteOwner ) != QFile::WriteOwner ||
+ ( perms & QFile::ReadOwner ) != QFile::ReadOwner ) {
+ // TODO: vkError perms
+ }
+ }
+#endif
+ } break;
+
case VALKYRIE::VG_EXEC: {
- /* see if we have an executable with rx permissions */
+ // see if we have an executable with rx permissions
argval = binaryCheck( &errval, argval );
if ( errval != PARSED_OK )
return errval;
- /* check the version */
+ // check the version
QString cmd = argval + " --version 2>&1";
FILE* fp;
char line[50];
@@ -428,7 +508,7 @@
if ( !vg_version.startsWith("valgrind") ) {
return PERROR_BADFILE;
}
- /* compare with minimum req'd version: */
+ // compare with minimum req'd version
int versionVg = strVersion2hex( vg_version );
int versionVgReqd = strVersion2hex( pchVersionVgMin );
if ( versionVg == -1 || versionVgReqd == -1) {
@@ -437,7 +517,8 @@
if ( versionVg < versionVgReqd ) {
return PERROR_BADVERSION;
}
- /* looking good... */
+
+ // if we get here, we're fine.
} break;
case VALKYRIE::VIEW_LOG:
@@ -454,11 +535,12 @@
m_startRunState = VkRunState::VALGRIND;
break;
- /* can't really test this */
+
case VALKYRIE::BIN_FLAGS:
+ // Can't test this.
break;
- /* ignore these opts */
+ // ignore these opts
case VALKYRIE::HELP:
case VALKYRIE::VGHELP:
case VALKYRIE::OPT_VERSION:
@@ -477,6 +559,23 @@
/*!
+ Find the option owner, find option within that owner.
+*/
+VkOption* Valkyrie::findOption( QString optGrp, int optid )
+{
+ VkObjectList objList = this->vkObjList();
+ for (int i = 0; i < objList.size(); ++i) {
+ VkObject* obj = objList.at(i);
+
+ if ( obj->objectName() == optGrp ) {
+ return obj->getOption( optid );
+ }
+ }
+ return NULL;
+}
+
+
+/*!
Return list of all VkObjects
*/
const VkObjectList Valkyrie::vkObjList()
Modified: branches/valkyrie_qt4port/objects/valkyrie_object.h
===================================================================
--- branches/valkyrie_qt4port/objects/valkyrie_object.h 2010-01-08 09:18:57 UTC (rev 463)
+++ branches/valkyrie_qt4port/objects/valkyrie_object.h 2010-01-08 21:43:43 UTC (rev 464)
@@ -71,8 +71,12 @@
#endif
unsigned int maxOptId() { return VALKYRIE::NUM_OPTS; }
+ int checkOptArg( QString optGrp, int optid, QString& argval );
int checkOptArg( int optid, QString& argval );
+ void updateConfig( QString optGrp, int optid, QString& argval );
+ void updateConfig( int optid, QString& argval );
+
// Generate own options page
VkOptionsPage* createVkOptionsPage();
@@ -80,6 +84,10 @@
virtual void setConfigDefaults();
+
+
+ VkOption* findOption( QString optGrp, int optid );
+
// list of all objects
const VkObjectList vkObjList();
// VkObject* vkObject( int objId );
Modified: branches/valkyrie_qt4port/objects/vk_objects.cpp
===================================================================
--- branches/valkyrie_qt4port/objects/vk_objects.cpp 2010-01-08 09:18:57 UTC (rev 463)
+++ branches/valkyrie_qt4port/objects/vk_objects.cpp 2010-01-08 21:43:43 UTC (rev 464)
@@ -22,6 +22,7 @@
#include "objects/vk_objects.h"
#include "utils/vk_config.h"
#include "options/vk_option.h"
+#include "utils/vk_utils.h"
@@ -52,7 +53,33 @@
}
+/*!
+ Return entire optionhash for this object
+*/
+OptionHash& VkObject::getOptions()
+{
+ return options.getOptionHash();
+}
+
+/*!
+ Update config - general case
+*/
+void VkObject::updateConfig( int optid, QString& argval )
+{
+ vk_assert( optid >= 0 && optid < VALKYRIE::NUM_OPTS );
+
+ VkOption* opt = getOption( optid );
+ vk_assert( opt != NULL );
+
+ vkConfig->setValue( opt->configKey(), argval );
+}
+
+
+
+/*!
+ Setup factory defaults
+*/
void VkObject::setConfigDefaults()
{
vkConfig->beginGroup( this->objectName() );
Modified: branches/valkyrie_qt4port/objects/vk_objects.h
===================================================================
--- branches/valkyrie_qt4port/objects/vk_objects.h 2010-01-08 09:18:57 UTC (rev 463)
+++ branches/valkyrie_qt4port/objects/vk_objects.h 2010-01-08 21:43:43 UTC (rev 464)
@@ -51,6 +51,7 @@
called by parseCmdArgs() and gui option pages */
virtual int checkOptArg( int optid, QString& argval ) = 0;
+ virtual void updateConfig( int optid, QString& argval );
/*! Set default config entries for thies object */
virtual void setConfigDefaults();
@@ -58,12 +59,11 @@
virtual VkOptionsPage* createVkOptionsPage() = 0;
VkOption* getOption( int optid );
+ OptionHash& getOptions();
protected:
virtual void setupOptions() = 0;
VkOptionHash options;
-
-
};
Modified: branches/valkyrie_qt4port/options/valgrind_options_page.cpp
===================================================================
--- branches/valkyrie_qt4port/options/valgrind_options_page.cpp 2010-01-08 09:18:57 UTC (rev 463)
+++ branches/valkyrie_qt4port/options/valgrind_options_page.cpp 2010-01-08 21:43:43 UTC (rev 464)
@@ -321,9 +321,9 @@
/* called when user clicks "Apply" / "Ok" / "Reset" buttons. */
void ValgrindOptionsPage::applyOption( int optId )
{
+ vk_assert( optId >= 0 && optId < VALGRIND::NUM_OPTS );
+
#if 0
- vk_assert( optId >= 0 && optId < Valgrind::NUM_OPTS );
-
// QString argval = m_itemList[optId]->currValue();
/* apply option */
Modified: branches/valkyrie_qt4port/options/valkyrie_options_page.cpp
===================================================================
--- branches/valkyrie_qt4port/options/valkyrie_options_page.cpp 2010-01-08 09:18:57 UTC (rev 463)
+++ branches/valkyrie_qt4port/options/valkyrie_options_page.cpp 2010-01-08 21:43:43 UTC (rev 464)
@@ -196,16 +196,15 @@
/* called when user clicks "Apply" / "Ok" / "Reset" buttons. */
void ValkyrieOptionsPage::applyOption( int optId )
{
- std::cerr << "vk-applyOption(): 0 (" << optId << ")" << std::endl;
+// std::cerr << "vk-applyOption(): 0 (" << optId << ")" << std::endl;
+ vk_assert( optId >= 0 && optId < VALKYRIE::NUM_OPTS );
- vk_assert( optId >= 0 && optId < VALKYRIE::NUM_OPTS );
-
OptionWidget* optWidg = m_itemList[optId];
vk_assert( optWidg != 0 );
QString argval = optWidg->currValue();
- std::cerr << "applyOption(): 1" << std::endl;
+// std::cerr << "applyOption(): 1" << std::endl;
/* apply option */
switch ( optId ) {
Modified: branches/valkyrie_qt4port/options/vk_option.cpp
===================================================================
--- branches/valkyrie_qt4port/options/vk_option.cpp 2010-01-08 09:18:57 UTC (rev 463)
+++ branches/valkyrie_qt4port/options/vk_option.cpp 2010-01-08 21:43:43 UTC (rev 464)
@@ -37,6 +37,65 @@
+
+/*!
+ Map error int to error string
+*/
+const char* parseErrString( const int error )
+{
+ switch ( error ) {
+ case PERROR_NODASH:
+ return "Short options do not require a '='";
+ case PERROR_NOARG:
+ return "Missing argument";
+ case PERROR_BADARG:
+ return "Invalid argument";
+ case PERROR_BADOPT:
+ return "Unknown/Disabled option";
+ case PERROR_BADOPERATION:
+ return "Mutually exclusive logical operations requested";
+ case PERROR_NULLARG:
+ return "opt->arg should not be NULL";
+ case PERROR_BADQUOTE:
+ return "Error in parameter quoting";
+ case PERROR_BADNUMBER:
+ return "Invalid numeric value";
+ case PERROR_OUTOFRANGE:
+ return "Numeric value outside valid range";
+ case PERROR_OVERFLOW:
+ return "Number too large or too small";
+ case PERROR_MALLOC:
+ return "Memory allocation failed";
+ case PERROR_BADDIR:
+ return "Invalid directory";
+ case PERROR_BADFILE:
+ return "Invalid file";
+ case PERROR_BADNUMFILES:
+ return "Invalid number of files ( max == 10 )";
+ case PERROR_BADFILERD:
+ return "You do not have read permission";
+ case PERROR_BADFILEWR:
+ return "You do not have write permission";
+ case PERROR_BADEXEC:
+ return "You do not have executable permission";
+ case PERROR_DB_CONFLICT:
+ return "Conflicting argument\n"
+ "--db-attach=yes conflicts with --trace-children=yes\n"
+ "Please choose one or the other, but not both.";
+ case PERROR_DB_OUTPUT:
+ return "using --db-attach=yes only makes sense "
+ "when sending output to stderr.";
+ case PERROR_POWER_OF_TWO:
+ return "number is not a power of two";
+ case PERROR_BADVERSION:
+ return "Bad program version";
+ default:
+ return "unknown error";
+ }
+}
+
+
+
/***************************************************************************/
/*!
Constructs a VkOptionHash
Modified: branches/valkyrie_qt4port/options/vk_option.h
===================================================================
--- branches/valkyrie_qt4port/options/vk_option.h 2010-01-08 09:18:57 UTC (rev 463)
+++ branches/valkyrie_qt4port/options/vk_option.h 2010-01-08 21:43:43 UTC (rev 464)
@@ -103,9 +103,9 @@
QString binaryCheck( int* err_val, const QString exe_name );
QString dirCheck( int* err_val, const QString fpath,
bool rd_perms, bool wr_perms );
+#endif
const char* parseErrString( const int error );
-#endif
Modified: branches/valkyrie_qt4port/options/vk_options_page.cpp
===================================================================
--- branches/valkyrie_qt4port/options/vk_options_page.cpp 2010-01-08 09:18:57 UTC (rev 463)
+++ branches/valkyrie_qt4port/options/vk_options_page.cpp 2010-01-08 21:43:43 UTC (rev 464)
@@ -148,7 +148,7 @@
if ( m_editList.isEmpty() && m_mod == false )
return true;
- std::cerr << "applyEDITS(): 2" << std::endl;
+// std::cerr << "applyEDITS(): 2" << std::endl;
// user clicked Ok/Apply after editing some items
@@ -159,9 +159,9 @@
if ( !checkOption( optw->id() ) ) {
return false;
}
- std::cerr << "applyEDITS(): 3 (" << i << ")" << std::endl;
+// std::cerr << "applyEDITS(): 3 (" << i << ")" << std::endl;
- // update any Valkyrie state dependent on this option
+ // update any Valkyrie state dependent on this option
applyOption( optw->id() );
}
std::cerr << "applyEDITS(): 4" << std::endl;
Added: branches/valkyrie_qt4port/options/vk_parse_cmdline.cpp
===================================================================
--- branches/valkyrie_qt4port/options/vk_parse_cmdline.cpp (rev 0)
+++ branches/valkyrie_qt4port/options/vk_parse_cmdline.cpp 2010-01-08 21:43:43 UTC (rev 464)
@@ -0,0 +1,293 @@
+/****************************************************************************
+** Parse command-line options implementation
+** - Called from main() to parse both valkyrie and valgrind args
+** --------------------------------------------------------------------------
+**
+** Copyright (C) 2000-2010, OpenWorks LLP. All rights reserved.
+** <in...@op...>
+**
+** This file is part of Valkyrie, a front-end for Valgrind.
+**
+** This file may be used under the terms of the GNU General Public
+** License version 2.0 as published by the Free Software Foundation
+** and appearing in the file COPYING included in the packaging of
+** this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include "objects/vk_objects.h"
+#include "objects/valkyrie_object.h" // for VALKYRIE::enums
+
+#include "utils/vk_utils.h"
+#include "options/vk_popt.h"
+#include "options/vk_option.h" // namespace VkOPT
+#include "utils/vk_config.h"
+
+
+void showHelp( vkPoptContext con, char key, Valkyrie* vk )
+{
+ QString VkName = vkConfig->vkName;
+ VkName.replace( 0, 1, vkConfig->vkName[0].toUpper() );
+
+ switch ( key ) {
+ case 'v':
+ printf("%s-%s\n", vkConfig->vkName.toLatin1().constData(),
+ vkConfig->vkVersion.toLatin1().constData() );
+ break;
+
+ case 'h':
+ vkPoptPrintHelp( con, stdout, vk->objectName().toLatin1().constData() );
+ printf( "\n%s is copyright %s %s\n"
+ "and licensed under the GNU General Public License, version 2.\n"
+ "Bug reports, feedback, praise, abuse, etc, to <%s>\n\n",
+ VkName.toLatin1().constData(),
+ vkConfig->vkCopyright.toLatin1().constData(),
+ vkConfig->vkAuthor.toLatin1().constData(),
+ vkConfig->vkEmail.toLatin1().constData() );
+ break;
+
+ case 'V':
+ vkPoptPrintHelp( con, stdout, NULL );
+ printf("\n%s is copyright %s %s\n",
+ VkName.toLatin1().constData(),
+ vkConfig->vkCopyright.toLatin1().constData(),
+ vkConfig->vkAuthor.toLatin1().constData() );
+//TODO
+// printf("Valgrind is copyright %s\n\n", vkConfig->vgCopyright.toLatin1().constData() );
+ break;
+
+ default:
+ vk_assert_never_reached();
+ }
+}
+
+
+void parseError( vkPoptContext con, const int err )
+{
+ // don't print anything; sender is dealing with msgs
+ if ( err != PERROR_DEFAULT ) {
+ fprintf( stderr, "%s: Parse error [%s] : %s\n",
+ vkConfig->vkName.toLatin1().constData(),
+ vkPoptBadOption(con),
+ parseErrString( err ) );
+ fprintf( stderr, "%s: Use --help for more information.\n",
+ vkConfig->vkName.toLatin1().constData() );
+ }
+}
+
+
+/*!
+ getObjOptions()
+ Determine the total no. of option structs required by counting the
+ no. of entries in the optList. Note: num_options = optList+1
+ because we need a NULL option entry to terminate each option array.
+*/
+vkPoptOption* getObjOptions( /*IN */VkObject* obj,
+ /*OUT*/vkPoptOption* vkOpts )
+{
+ vk_assert( obj != NULL );
+ vk_assert( vkOpts != NULL );
+
+ int idx = 0;
+ OptionHash opthash = obj->getOptions();
+ for ( Iter_OptionHash it = opthash.begin(); it != opthash.end(); ++it ) {
+ VkOption* opt = it.value();
+ vk_assert( opt != NULL );
+
+ // ignore non-popt options
+ if ( opt->argType == VkOPT::NOT_POPT )
+ continue;
+
+ vkPoptOption* vkopt = &vkOpts[idx++];
+ vkopt->arg = NULL;
+ vkopt->optId = opt->optid;
+ vkopt->argType = opt->argType;
+ vkopt->shortFlag = opt->shortFlag.toLatin1();
+
+ vkopt->optGrp = (char*)malloc( opt->configGrp.length()+1 );
+ strncpy( vkopt->optGrp, opt->configGrp.toLatin1().data(), opt->configGrp.length()+1 );
+
+ vkopt->longFlag = (char*)malloc( opt->longFlag.length()+1 );
+ strncpy( vkopt->longFlag, opt->longFlag.toLatin1().data(), opt->longFlag.length()+1 );
+
+ vkopt->helptxt = (char*)malloc( opt->longHelp.length()+1 );
+ strncpy( vkopt->helptxt, opt->longHelp.toLatin1().data(), opt->longHelp.length()+1 );
+
+ vkopt->helpdesc = (char*)malloc( opt->flagDescr.length()+1 );
+ strncpy( vkopt->helpdesc, opt->flagDescr.toLatin1().data(), opt->flagDescr.length()+1 );
+ }
+ // null entry terminator
+ vkOpts[idx] = nullOpt();
+ return vkOpts;
+}
+
+
+void getAllOptions( /*IN */VkObjectList objList,
+ /*OUT*/vkPoptOption* allOpts )
+{
+ int nopts, idx = 0;
+ size_t nbytes;
+ vkPoptOption* vkOpts;
+ vk_assert( allOpts != NULL );
+
+ for (int i = 0; i < objList.size(); ++i) {
+ VkObject* obj = objList.at(i);
+
+ // allocate mem for this object's options
+ nopts = obj->getOptions().count();
+ nbytes = sizeof(vkPoptOption) * (nopts + 1/*null end*/);
+ vkOpts = (vkPoptOption*)malloc( nbytes );
+
+ vkPoptOption* tblOpt = &allOpts[idx++];
+ *tblOpt = nullOpt(); // init null struct
+ tblOpt->arg = getObjOptions( obj, vkOpts ); // get this object's options
+ // set table name to option group name
+ tblOpt->optGrp = (char*)malloc( obj->objectName().length()+1 );
+ strncpy( tblOpt->optGrp, obj->objectName().toLatin1().data(), obj->objectName().length()+1 );
+ }
+ // null entry terminator
+ allOpts[idx] = nullOpt();
+}
+
+
+void freeOptions( vkPoptOption* opt )
+{
+ for (; opt && opt->optGrp; opt++ ) {
+ // recurse and free the opt tree.
+ if ( opt->arg != NULL ) {
+ freeOptions( opt->arg );
+ _free( opt->arg ); // Do free non-top level opts
+ }
+ _free( opt->optGrp );
+ _free( opt->longFlag );
+ _free( opt->helptxt );
+ _free( opt->helpdesc );
+ // Don't free top level opts: allocated on stack.
+ }
+}
+
+
+bool parseCmdArgs( int argc, char** argv, Valkyrie* vk,
+ bool& show_help_and_exit )
+{
+ int rc = PARSED_OK; // check fn return value / err value
+ bool ret = true; // return value
+ show_help_and_exit = false; // just quit.
+ char argVal[512]; // store argument values for checking
+
+ // --------------------------------------------------
+ // fetch all object options
+ VkObjectList objList = vk->vkObjList();
+ int num_objs = objList.count();
+ vkPoptOption allOpts[num_objs+1/*null end*/];
+ getAllOptions( objList, allOpts );
+
+#if 0 // TODO: rm when done debugging
+ cerr << "PRINTOUT" << endl;
+ for ( int i=0; i<num_objs; i++) {
+ vkPoptOption* opt = &allOpts[i];
+ cerr << "TABLE: " << opt->optGrp << endl;
+
+ opt = opt->arg;
+ while ( opt && opt->optId != -1 ) {
+ cerr << opt->optGrp << ", " << opt->optId << ", " << opt->longFlag << endl;
+ opt++;
+ }
+ }
+#endif
+
+
+ // --------------------------------------------------
+ // context for parsing cmd-line opts
+ vkPoptContext optCon =
+ vkPoptGetContext( argc, (const char**)argv, allOpts );
+
+ // --------------------------------------------------
+ // process the options
+ while ( true ) {
+ const vkPoptOption* opt = NULL;
+ bool done_vk_flags = false;
+ rc = vkPoptGetNextOpt( optCon, argVal, &opt, done_vk_flags );
+
+ if ( rc != PARSED_OK ) {
+ // an error occurred during option processing
+ parseError( optCon, rc );
+ ret = false;
+ goto done;
+ }
+
+ if ( done_vk_flags ) {
+ // no more vk/vg flags - continue on.
+ break;
+ }
+
+ vk_assert(opt);
+
+ // Just show help and exit?
+ char vk_arg = opt->shortFlag;
+ // printf("vk_arg: '%c'\n", vk_arg);
+ if ( vk_arg == 'h' || vk_arg == 'v' || vk_arg == 'V' ) {
+ showHelp( optCon, vk_arg, vk );
+ show_help_and_exit = true;
+ goto done;
+ }
+
+ // vkObjects check their own arguments
+ QString qs_argval = argVal;
+ rc = vk->checkOptArg( opt->optGrp, opt->optId, qs_argval );
+
+ if ( rc != PARSED_OK ) {
+ parseError( optCon, rc );
+ ret = false;
+ goto done;
+ }
+
+ vk->updateConfig( opt->optGrp, opt->optId, qs_argval );
+
+ } // end while.
+
+
+ // --------------------------------------------------
+ // Get the leftovers: should only be 'myprog --myflags'.
+ // - Check we really do have a valid prog-to-debug here.
+ // If yes, then assume all subsequent flags belong to it.
+ if ( vkPoptPeekArg(optCon) != NULL ) {
+
+ // First get myprog
+ QString qs_argval = vkPoptGetArg(optCon);
+ rc = vk->checkOptArg( VALKYRIE::BINARY, qs_argval );
+ if ( rc != PARSED_OK ) {
+ parseError( optCon, rc );
+ ret = false;
+ goto done;
+ }
+ vk->updateConfig( VALKYRIE::BINARY, qs_argval );
+
+ // Get myprog's flags, if any
+ const char **args = vkPoptGetArgs( optCon );
+ QStringList aList;
+ for ( int i=0; args && args[i] != NULL; i++ ) {
+ aList << args[i];
+ }
+ qs_argval = aList.isEmpty() ? "" : aList.join( " " );
+ rc = vk->checkOptArg( vk->objectName(), VALKYRIE::BIN_FLAGS, qs_argval );
+
+ if ( rc != PARSED_OK ) {
+ parseError( optCon, rc );
+ ret = false;
+ goto done;
+ }
+ vk->updateConfig( VALKYRIE::BIN_FLAGS, qs_argval );
+ }
+
+
+done:
+ // --------------------------------------------------
+ // Cleanup
+ freeOptions( allOpts );
+ vkPoptFreeContext( optCon );
+ return ret;
+}
Added: branches/valkyrie_qt4port/options/vk_parse_cmdline.h
===================================================================
--- branches/valkyrie_qt4port/options/vk_parse_cmdline.h (rev 0)
+++ branches/valkyrie_qt4port/options/vk_parse_cmdline.h 2010-01-08 21:43:43 UTC (rev 464)
@@ -0,0 +1,33 @@
+/****************************************************************************
+** Parse command-line options
+** - Called from main() to parse both valkyrie and valgrind args
+** --------------------------------------------------------------------------
+**
+** Copyright (C) 2000-2010, OpenWorks LLP. All rights reserved.
+** <in...@op...>
+**
+** This file is part of Valkyrie, a front-end for Valgrind.
+**
+** This file may be used under the terms of the GNU General Public
+** License version 2.0 as published by the Free Software Foundation
+** and appearing in the file COPYING included in the packaging of
+** this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef __VK_PARSE_CMDLINE_H
+#define __VK_PARSE_CMDLINE_H
+
+
+/*!
+ parseCmdArgs()
+ Command-line args parsing, updates global config settings.
+*/
+extern bool parseCmdArgs( int argc, char** argv, Valkyrie* vk,
+ bool& show_help_and_exit );
+
+#endif // #ifndef __VK_PARSE_CMDLINE_H
+
Added: branches/valkyrie_qt4port/options/vk_popt.cpp
===================================================================
--- branches/valkyrie_qt4port/options/vk_popt.cpp (rev 0)
+++ branches/valkyrie_qt4port/options/vk_popt.cpp 2010-01-08 21:43:43 UTC (rev 464)
@@ -0,0 +1,640 @@
+/****************************************************************************
+** Implementation of Popt functions
+** This is a seriously hacked version of the popt libraries.
+** No credit to me, all thanks and many apologies to the Red Hat team
+** --------------------------------------------------------------------------
+** popt is Copyright (C) 1998 Red Hat Software and distributed under
+** an X11-style license, which is in turn compatible the GNU GPL v.2.
+** See the file COPYING for the full license details.
+*/
+
+#include "options/vk_popt.h"
+#include "options/vk_option.h" // namespace VkOPT
+#include "utils/vk_utils.h"
+
+
+/*!
+ return a vkPoptOption initialised to null
+*/
+vkPoptOption nullOpt()
+{
+ vkPoptOption _nullOpt = TABLE_END;
+ return _nullOpt;
+}
+
+const char * vkPoptPeekArg( vkPoptContext con )
+{
+ const char * ret = NULL;
+ if ( con && con->leftovers != NULL &&
+ con->nextLeftover < con->numLeftovers )
+ ret = con->leftovers[con->nextLeftover];
+ return ret;
+}
+
+
+const char * vkPoptGetArg( vkPoptContext con )
+{
+ const char * ret = NULL;
+ if ( con && con->leftovers != NULL &&
+ con->nextLeftover < con->numLeftovers ) {
+ ret = con->leftovers[con->nextLeftover++];
+ }
+ return ret;
+}
+
+
+const char ** vkPoptGetArgs( vkPoptContext con )
+{
+ if ( con == NULL || con->leftovers == NULL ||
+ con->numLeftovers == con->nextLeftover )
+ return NULL;
+
+ // some apps like [like RPM ;-) ] need this NULL terminated
+ con->leftovers[con->numLeftovers] = NULL;
+ return (con->leftovers + con->nextLeftover);
+}
+
+
+vkPoptContext vkPoptGetContext( int argc, const char ** argv,
+ const vkPoptOption * options )
+{
+ vkPoptContext con = (vkPoptContext)malloc( sizeof(*con) );
+
+ if ( con == NULL ) {
+ return NULL;
+ }
+
+ memset( con, 0, sizeof(*con) );
+
+ con->os = con->optionStack;
+ con->os->argc = argc;
+ con->os->argv = argv;
+ con->os->next = 1; // skip argv[0]
+ con->leftovers = (const char**)calloc( (argc + 1), sizeof(*con->leftovers) );
+ con->options = options;
+ con->flags = PCONTEXT_POSIXMEHARDER;
+ con->finalArgvAlloced = argc * 2;
+ con->finalArgv = (const char**)calloc( con->finalArgvAlloced,
+ sizeof(*con->finalArgv) );
+
+ return con;
+}
+
+
+static void vkCleanOSE( struct optionStackEntry *os )
+{
+ os->nextArg = (const char*)_free( os->nextArg );
+ os->argv = (const char**)_free( os->argv );
+}
+
+
+const vkPoptOption * vkFindOption( const vkPoptOption * opt,
+ const char * longFlag,
+ char shortFlag,
+ int singleDash )
+{
+ // this happens when a single - is given
+ if ( singleDash && !shortFlag && (longFlag && *longFlag == '\0') )
+ shortFlag = '-';
+
+ for (; opt->longFlag || opt->shortFlag || opt->arg; opt++) {
+
+ if ( opt->arg != NULL ) { // is-a table
+ // recurse on included sub-tables.
+ const vkPoptOption* opt2 = vkFindOption( opt->arg, longFlag, shortFlag, singleDash );
+ if ( opt2 == NULL ) {
+ // no match in sub-table
+ continue;
+ }
+ // found match: return option
+ return opt2;
+ }
+ else { // is-a leaf
+ if ( longFlag && opt->longFlag && !singleDash &&
+ !strcmp( longFlag, opt->longFlag ) ) {
+ // longFlag match
+ break;
+ }
+ if (shortFlag && shortFlag == opt->shortFlag) {
+ // shortFlag match
+ break;
+ }
+ }
+ }
+
+ if ( !opt->longFlag && !opt->shortFlag ) {
+ // end of optArr: no match found
+ return NULL;
+ }
+
+ // found match
+ return opt;
+}
+
+
+static const char * vkExpandNextArg( const char * s )
+{
+ char *t, *te;
+ size_t tn = strlen(s) + 1;
+ char c;
+
+ te = t = (char*)malloc(tn);;
+ if ( t == NULL )
+ return NULL;
+ while ((c = *s++) != '\0') {
+ *te++ = c;
+ }
+
+ *te = '\0';
+ // memory leak, hard to plug
+ t = (char*)realloc(t, strlen(t) + 1);
+ return t;
+}
+
+
+/*!
+ get next option opt_ret
+ returns 0 on success, PERROR_* on error
+*/
+int vkPoptGetNextOpt( vkPoptContext con,
+ char *arg_val/*OUT*/,
+ const vkPoptOption** opt_ret/*OUT*/,
+ bool& done_vk_flags/*OUT*/ )
+{
+ const vkPoptOption * opt = NULL;
+ int done = 0;
+
+ if ( con == NULL ) {
+ done_vk_flags = true;
+ return PARSED_OK;
+ }
+
+ while ( !done ) {
+ const char * origOptString = NULL;
+ const char * longArg = NULL;
+ int shorty = 0;
+
+ while ( !con->os->nextCharArg &&
+ con->os->next == con->os->argc &&
+ con->os > con->optionStack ) {
+ vkCleanOSE( con->os-- );
+ }
+
+ if ( !con->os->nextCharArg &&
+ con->os->next == con->os->argc ) {
+ done_vk_flags = true;
+ *opt_ret = opt;
+ return PARSED_OK;
+ }
+
+ // process next long option
+ if ( !con->os->nextCharArg ) {
+ char * localOptString, * optString;
+ int thisopt;
+ thisopt = con->os->next;
+ if ( con->os->argv != NULL )
+ origOptString = con->os->argv[con->os->next++];
+
+ if ( origOptString == NULL ) {
+ return PERROR_BADOPT;
+ }
+ if ( strcmp(origOptString, "--") == 0 ) {
+ return PERROR_BADQUOTE;
+ }
+
+ if ( con->restLeftover || *origOptString != '-' ) {
+ if ( con->flags & PCONTEXT_POSIXMEHARDER )
+ con->restLeftover = 1;
+ if ( con->leftovers != NULL )
+ con->leftovers[con->numLeftovers++] = origOptString;
+ continue;
+ }
+
+ // make a copy we can hack at
+ localOptString = optString =
+ strcpy((char*)alloca(strlen(origOptString) + 1), origOptString);
+
+ if ( optString[0] == '\0' )
+ return PERROR_BADOPT;
+
+ if ( optString[1] == '-' && !optString[2] ) {
+ con->restLeftover = 1;
+ continue;
+ } else {
+ char *oe;
+ int singleDash;
+ optString++;
+ if ( *optString == '-' )
+ singleDash = 0, optString++;
+ else
+ singleDash = 1;
+
+ // Check for "--long=arg" option
+ for ( oe = optString; *oe && *oe != '='; oe++ )
+ { };
+ if ( *oe == '=' ) {
+ // FIX: don't use '=' for shortopts
+ if ( singleDash )
+ return PERROR_NODASH;
+ *oe++ = '\0';
+
+ // longArg is mapped back to persistent storage.
+ longArg = origOptString + (oe - localOptString);
+
+ // FIX: catch cases where --longarg=<no-arg>
+ if ( strlen(longArg) == 0 ) {
+ printf("1: returning PERROR_NOARG\n");
+ return PERROR_NOARG;
+ }
+ }
+#if 0
+ else if ( singleDash == 0 ) {
+ /* FIX: catch cases where we didn't find an '=',
+ and this is a --longarg option */
+ //printf("2: returning PERROR_NOARG\n");
+ return PERROR_NOARG;
+ }
+#endif
+
+ opt = vkFindOption( con->options, optString,
+ '\0', singleDash );
+ if ( !opt && !singleDash ) {
+ printf("returning PERROR_BADOPT\n");
+ return PERROR_BADOPT;
+ }
+ }
+
+ if ( !opt ) {
+ con->os->nextCharArg = origOptString + 1;
+ } else {
+ shorty = 0;
+ }
+ }
+
+ // process next short option
+ if ( con->os->nextCharArg ) {
+ origOptString = con->os->nextCharArg;
+ con->os->nextCharArg = NULL;
+
+ opt = vkFindOption( con->options, NULL, *origOptString, 0 );
+ if ( !opt ) {
+ return PERROR_BADOPT;
+ }
+ shorty = 1;
+
+ origOptString++;
+ if ( *origOptString != '\0' )
+ con->os->nextCharArg = origOptString;
+ }
+
+ if ( opt == NULL )
+ return PERROR_BADOPT;
+
+ if ( opt->argType != VkOPT::ARG_NONE ) {
+ con->os->nextArg = (const char*)_free(con->os->nextArg);
+ if ( longArg ) {
+ longArg = vkExpandNextArg( longArg );
+ con->os->nextArg = longArg;
+ } else if ( con->os->nextCharArg ) {
+ longArg = vkExpandNextArg( con->os->nextCharArg);
+ con->os->nextArg = longArg;
+ con->os->nextCharArg = NULL;
+ } else {
+ while ( con->os->next == con->os->argc &&
+ con->os > con->optionStack ) {
+ vkCleanOSE( con->os-- );
+ }
+ if ( con->os->next == con->os->argc ) {
+ // FIX: con->os->argv not defined
+ return PERROR_NOARG;
+ con->os->nextArg = NULL;
+ } else {
+ if ( con->os->argv != NULL ) {
+ // watch out: subtle side-effects live here.
+ longArg = con->os->argv[con->os->next++];
+ longArg = vkExpandNextArg( longArg );
+ con->os->nextArg = longArg;
+ }
+ }
+ }
+ longArg = NULL;
+
+ // store the argument value for checking
+ if ( con->os->nextArg ) {
+ sprintf( arg_val, "%s", con->os->nextArg );
+ }
+ } // end of "if ! VkOPT::ARG_NONE"
+
+ if ( opt->optId >= 0 ) { // is-a leaf
+ done = 1;
+ }
+
+ if ( (con->finalArgvCount + 2) >= (con->finalArgvAlloced) ) {
+ con->finalArgvAlloced += 10;
+ con->finalArgv = (const char**)realloc(con->finalArgv,
+ sizeof(*con->finalArgv) * con->finalArgvAlloced);
+ }
+
+ if ( con->finalArgv != NULL ) {
+ char *s = (char*)malloc((opt->longFlag ? strlen(opt->longFlag) : 0) + 3);
+ if ( s != NULL ) {
+ if ( opt->longFlag ) {
+ sprintf(s, "--%s", opt->longFlag);
+ } else {
+ sprintf(s, "-%c", opt->shortFlag);
+ }
+ con->finalArgv[con->finalArgvCount++] = s;
+ } else
+ con->finalArgv[con->finalArgvCount++] = NULL;
+ }
+
+ if ((opt->arg == NULL/* leaf */) &&
+ (opt->argType != VkOPT::ARG_NONE)) {
+ if (con->finalArgv != NULL && con->os->nextArg) {
+ char* s = (char*)malloc( strlen(con->os->nextArg)+1 );
+ if (s == NULL) {
+ vkPrintErr("virtual memory exhausted.");
+ exit(EXIT_FAILURE);
+ } else {
+ con->finalArgv[con->finalArgvCount++] =
+ strcpy( s, con->os->nextArg );
+ }
+ }
+ }
+ } // end while ( !done )
+
+ //vk_assert( opt != NULL );
+ *opt_ret = opt;
+ return PARSED_OK;
+}
+
+
+vkPoptContext vkPoptFreeContext( vkPoptContext con )
+{
+ if ( con == NULL )
+ return con;
+
+ // poptResetContext( con );
+ int i;
+ while ( con->os > con->optionStack ) {
+ vkCleanOSE(con->os--);
+ }
+ con->os->nextCharArg = NULL;
+ con->os->nextArg = NULL;
+ con->os->next = 1; // skip argv[0]
+ con->numLeftovers = 0;
+ con->nextLeftover = 0;
+ con->restLeftover = 0;
+
+ if ( con->finalArgv != NULL )
+ for (i = 0; i < con->finalArgvCount; i++)
+ con->finalArgv[i] = (const char*)_free(con->finalArgv[i]);
+ con->finalArgvCount = 0;
+
+ con->leftovers = (const char**)_free( con->leftovers );
+ con->finalArgv = (const char**)_free( con->finalArgv );
+
+ con = (vkPoptContext)_free( con );
+ return con;
+}
+
+
+const char * vkPoptBadOption( vkPoptContext con )
+{
+ struct optionStackEntry * os = NULL;
+
+ if ( con != NULL )
+ os = con->optionStack;
+
+ return ( os && os->argv ? os->argv[os->next - 1] : NULL );
+}
+
+
+
+/* ------ help printing stuff --------------------------------*/
+// set in poptPrintHelp
+static int leftColWidth = -1;
+
+
+static const char * vkGetHelpDesc( const vkPoptOption * opt )
+{
+ // if ARG_NONE: no arguments to describe
+ if ( opt->argType == VkOPT::ARG_NONE )
+ return NULL;
+
+ if ( opt->helpdesc )
+ return opt->helpdesc;
+
+ return NULL;
+}
+
+
+/*!
+ vkSingleOptionHelp()
+ called from vkTableHelp() for leaf table.
+*/
+static void vkSingleOptionHelp( FILE * fp,
+ const vkPoptOption * opt )
+{
+ int indentLength = leftColWidth + 2;
+ int lineLength = 80 - indentLength;
+ const char* help = opt->helptxt;
+ const char* helpdesc = vkGetHelpDesc( opt );
+ int helpLength;
+ char * defs = NULL;
+ char * left;
+ int nb = leftColWidth + 1;
+
+ // make sure there's more than enough room in target buffer.
+ if ( opt->longFlag )
+ nb += strlen( opt->longFlag );
+ if ( helpdesc )
+ nb += strlen( helpdesc );
+
+ left = (char*)malloc( nb );
+ if ( left == NULL )
+ return;
+ left[0] = '\0';
+ left[leftColWidth] = '\0';
+
+ if ( opt->longFlag && opt->shortFlag ) {
+ sprintf( left, "-%c, --%s", opt->shortFlag, opt->longFlag);
+ } else if (opt->shortFlag != '\0') {
+ sprintf( left, "-%c", opt->shortFlag);
+ } else if (opt->longFlag) {
+ sprintf( left, "--%s", opt->longFlag );
+ }
+
+ if ( !*left ) {
+ goto out;
+ }
+
+ if ( helpdesc ) {
+ char * le = left + strlen( left );
+ *le++ = ' ';
+ strcpy( le, helpdesc );
+ le += strlen(le);
+ *le = '\0';
+ }
+
+ if ( help ) {
+ fprintf( fp," %-*s", leftColWidth, left );
+ } else {
+ fprintf( fp," %s\n", left );
+ goto out;
+ }
+
+ left = (char*)_free(left);
+ if ( defs ) {
+ help = defs;
+ defs = NULL;
+ }
+
+ helpLength = strlen( help );
+ while ( helpLength > lineLength ) {
+ const char * ch;
+ char format[100];
+
+ ch = help + lineLength - 1;
+ while ( ch > help && !isspace(*ch) ) {
+ ch--;
+ }
+ if ( ch == help ) {
+ break; // give up
+ }
+ while ( ch > (help + 1) && isspace(*ch) ) {
+ ch--;
+ }
+ ch++;
+
+ sprintf( format, "%%.%ds\n%%%ds",
+ (int) (ch - help), indentLength );
+ fprintf( fp, format, help, " " );
+ help = ch;
+ while ( isspace(*help) && *help ) {
+ help++;
+ }
+ helpLength = strlen( help );
+ }
+
+ if ( helpLength )
+ fprintf( fp, "%s\n", help );
+
+ out:
+ defs = (char*)_free(defs);
+ left = (char*)_free(left);
+}
+
+
+static int vkMaxArgWidth( const vkPoptOption * opt )
+{
+ int max = 0;
+ int len = 0;
+ const char * s;
+
+ if ( opt == NULL )
+ return 0;
+
+ for (; opt->longFlag || opt->shortFlag || opt->arg; opt++ ) {
+
+ if ( opt->arg != NULL ) { // is-a table
+ // recurse on included sub-tables.
+ len = vkMaxArgWidth( opt->arg );
+ if ( len > max )
+ max = len;
+ }
+ else { // is-a leaf
+ len = sizeof(" ") - 1;
+ if ( opt->shortFlag != '\0' )
+ len += sizeof("-X")-1;
+ if ( opt->shortFlag != '\0' && opt->longFlag )
+ len += sizeof(", ")-1;
+ if (opt->longFlag) {
+ len += sizeof("--") - 1;
+ len += strlen( opt->longFlag );
+ }
+
+ s = vkGetHelpDesc( opt );
+ if ( s )
+ len += sizeof("=") - 1 + strlen( s );
+ if ( len > max )
+ max = len;
+ }
+ }
+ return max;
+}
+
+
+/*!
+ vkTableHelp()
+ this version prints nested tables first. swap 'em over if this
+ isn't the behaviour you want.
+*/
+static void vkTableHelp( FILE * fp, const vkPoptOption * opt )
+{
+ if ( opt == NULL )
+ return;
+
+ // recurse over all tables
+ for (; opt->longFlag || opt->shortFlag || opt->arg; opt++) {
+ if ( opt->arg != NULL ) { // is-a table
+ // print table title
+ fprintf( fp, "\n%s options:\n", opt->optGrp );
+ // recurse on included sub-tables.
+ vkTableHelp( fp, opt->arg );
+ }
+ else { // is-a leaf
+ // print options
+ vkSingleOptionHelp( fp, opt );
+ }
+ }
+}
+
+
+/*!
+ vkPoptPrintHelp()
+ if tableName == NULL, recurses over all tables;
+ else just prints contents of the specified table.
+*/
+void vkPoptPrintHelp( vkPoptContext con, FILE * fp,
+ const char * tableName )
+{
+ const char * fn;
+
+ fprintf( fp, "\nUsage:" );
+ fn = con->optionStack->argv[0];
+ if ( fn != NULL ) {
+ if ( strchr(fn, '/') )
+ fn = strrchr( fn, '/' ) + 1;
+ fprintf( fp, " %s", fn );
+ }
+
+ fprintf( fp, " %s",
+ "[valkyrie-opts] [valgrind-opts] [prog-and-args]\n" );
+
+ leftColWidth = vkMaxArgWidth( con->options );
+
+ if ( tableName == NULL ) {
+ // print all tables
+ vkTableHelp( fp, con->options );
+ } else {
+ // trawl through con->options till we find the right table
+ const vkPoptOption * opt;
+ for ( opt = con->options; (opt != NULL) &&
+ (opt->optGrp != NULL); opt++ ) {
+ if ( strcmp( opt->optGrp, tableName ) == 0 ) {
+ break;
+ }
+ }
+
+ // print the table:
+ if ( opt != NULL) {
+ if ( opt->optGrp != NULL )
+ fprintf( fp, "\n%s options:\n", opt->optGrp );
+ else
+ vkPrintErr("Error: vkPoptPrintHelp(): No match found for table '%s'.", tableName);
+ vkTableHelp( fp, opt->arg );
+ }
+ }
+
+}
Added: branches/valkyrie_qt4port/options/vk_popt.h
===================================================================
--- branches/valkyrie_qt4port/options/vk_popt.h (rev 0)
+++ branches/valkyrie_qt4port/options/vk_popt.h 2010-01-08 21:43:43 UTC (rev 464)
@@ -0,0 +1,129 @@
+/****************************************************************************
+** Definition of Popt functions
+** This is a seriously hacked version of the popt libraries.
+** No credit to me, all thanks and many apologies to the Red Hat team
+** --------------------------------------------------------------------------
+** popt is Copyright (C) 1998 Red Hat Software and distributed under
+** an X11-style license, which is in turn compatible the GNU GPL v.2.
+** See the file COPYING for the full license details.
+*/
+
+#ifndef __VK_POPT_H
+#define __VK_POPT_H
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "options/vk_option.h"
+
+
+#define OPTION_DEPTH 10
+
+// options can't follow args
+#define PCONTEXT_POSIXMEHARDER (1 << 2)
+
+/*!
+ vkPoptOption
+ This may be one of:
+ - TABLE_END: none set of: shortFlag && longFlag && arg
+ - table: arg = array of options, optGrp = table title
+ - option: arg = NULL, remaining vars filled
+*/
+typedef struct _vkPoptOption {
+ struct _vkPoptOption* arg; // table holds ptr to
+ char* optGrp; // opt group name: "valgrind" etc.
+ int optId; // eg. VIEW-LOG
+ VkOPT::ArgType argType; // option type: ARG_***
+ char shortFlag; // '\0' || 'h'
+ char* longFlag; // NULL || --help
+ char* helptxt; // help text
+ char* helpdesc; // eg. <file>
+} vkPoptOption;
+
+#define TABLE_END { NULL, NULL, -1, VkOPT::NOT_POPT, '\0', NULL, NULL, NULL }
+vkPoptOption nullOpt();
+
+
+typedef struct vkPoptContext_s* vkPoptContext;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* initialize popt context.
+ - argc no. of arguments
+ - argv argument array
+ - options address of popt option table
+ - returns initialized popt context */
+vkPoptContext vkPoptGetContext( int argc, const char ** argv,
+ const vkPoptOption * options );
+
+/* get next option opt_ret
+ returns 0 on success, PERROR_* on error */
+int vkPoptGetNextOpt( vkPoptContext con, char *arg_val,
+ const vkPoptOption** opt/*OUT*/,
+ bool& done_vk_flags/*OUT*/ );
+
+/* return current option's argument,
+ or NULL if no more options are available */
+const char * vkPoptGetArg( vkPoptContext con );
+
+/* return remaining argument array, terminated with NULL */
+const char ** vkPoptGetArgs( vkPoptContext con );
+
+/* peek at current option's argument */
+const char * vkPoptPeekArg( vkPoptContext con );
+
+/* return the offending option which caused the most recent error */
+const char * vkPoptBadOption( vkPoptContext con );
+
+/* destroy context. return NULL always */
+vkPoptContext vkPoptFreeContext( vkPoptContext con );
+
+/* print detailed description of options.
+ fp == ouput file handle */
+void vkPoptPrintHelp( vkPoptContext con, FILE * fp,
+ const char * tableName );
+
+#ifdef __cplusplus
+}
+#endif
+
+/*--------------------------------------------------*/
+/* wrapper to free(3), hides const compilation noise,
+ permit NULL, return NULL always */
+static inline void * _free( const void * p )
+{
+ if ( p != NULL )
+ free((void *)p);
+ return NULL;
+}
+
+
+struct optionStackEntry {
+ int argc;
+ const char ** argv;
+ int next;
+ const char * nextArg;
+ const char * nextCharArg;
+};
+
+
+struct vkPoptContext_s {
+ struct optionStackEntry optionStack[OPTION_DEPTH];
+ struct optionStackEntry * os;
+ const char ** leftovers;
+ int numLeftovers;
+ int nextLeftover;
+ const vkPoptOption * options;
+ int restLeftover;
+ int flags;
+ const char ** finalArgv;
+ int finalArgvCount;
+ int finalArgvAlloced;
+};
+
+
+#endif
Modified: branches/valkyrie_qt4port/utils/vk_config.cpp
===================================================================
--- branches/valkyrie_qt4port/utils/vk_config.cpp 2010-01-08 09:18:57 UTC (rev 463)
+++ branches/valkyrie_qt4port/utils/vk_config.cpp 2010-01-08 21:43:43 UTC (rev 464)
@@ -90,45 +90,30 @@
bool VkConfig::initCfg( Valkyrie* vk )
{
- // First: check Global config file exists: if not, create one from compiled defailts.
+ // 1) Check Global config file exists: if not, create one from compiled defailts.
if ( ! QFile::exists( vkCfgGlblFilename() ) ) {
writeConfigDefaults( vk );
}
- // Second: read global config file into RUNTIME settings
+ // 2) Read global config file into RUNTIME settings
// check at least owner read/write perms ok
QFile::Permissions perms = QFile::permissions( vkCfgGlblFilename() );
if ( ( perms & QFile::WriteOwner ) != QFile::WriteOwner ||
( perms & QFile::ReadOwner ) != QFile::ReadOwner ) {
- // TODO: vkError permissions
- } else {
- // first clear all current settings, then read in global
- this->clear();
- readFromGlblConfigFile();
- }
+//TODO
+ cerr << "TODO: vkError permissions on vkCfgGlblFilename" << endl;
- // Third: if given a Project file on the command line, read and update 'working' config
-#if 0 // TODO: command line args: project file (create if !exist)
- get proj_filename
-
- if ( QFile::exists( proj_filename ) ) {
- // check at least owner read/write perms ok
- QFile::Permissions perms = QFile::permissions( proj_filename );
- if ( ( perms & QFile::WriteOwner ) != QFile::WriteOwner ||
- ( perms & QFile::ReadOwner ) != QFile::ReadOwner ) {
- // TODO: vkError perms
- } else {
- vkCfgProjectFilePath = proj_filename;
-
- // don't clear current settings, just update from project cfg file
- readFromProjConfigFile();
- }
+ } else {
+ // first clear all current settings, then read in global
+ this->clear();
+ readFromGlblConfigFile();
}
-#endif
- // Fourth: Command line options update 'working' config
- // TODO
+ // 3) If given a Project file on the command line, read and update 'working' config
+ // Done by parseCmdArgs() -> vkObj::updateConfig(), called after us.
+ // 4) Command line options update 'working' config
+ // Done by parseCmdArgs(), called after us.
/*
vkFatal( 0, "Initialising Config",
@@ -150,10 +135,21 @@
*/
void VkConfig::createNewProject( QString& dir, QString& proj_name )
{
+ createNewProject( dir + "/" + proj_name + "." + VK_CFG_EXT );
+}
+
+
+/*!
+ VkConfig::createNewProject()
+ Sets project filename to given (new) project config file.
+ Writes the current config to the given new project config file.
+ */
+void VkConfig::createNewProject( QString proj_filename )
+{
// ensure any existing project settings are saved first.
vkConfig->sync();
- vkCfgProjectFilename = dir + "/" + proj_name + "." + VK_CFG_EXT;
+ vkCfgProjectFilename = proj_filename;
this->saveToProjConfigFile();
}
Modified: branches/valkyrie_qt4port/utils/vk_config.h
===================================================================
--- branches/valkyrie_qt4port/utils/vk_config.h 2010-01-08 09:18:57 UTC (rev 463)
+++ branches/valkyrie_qt4port/utils/vk_config.h 2010-01-08 21:43:43 UTC (rev 464)
@@ -74,7 +74,8 @@
bool initCfg( Valkyrie* vk );
void createNewProject( QString& dir, QString& proj_name );
- void openProject( QString& proj_name );
+ void createNewProject( QString proj_filename );
+ void openProject( QString& proj_filename );
void sync();
void readFromProjConfigFile();
Modified: branches/valkyrie_qt4port/valkyrie.pro
===================================================================
--- branches/valkyrie_qt4port/valkyrie.pro 2010-01-08 09:18:57 UTC (rev 463)
+++ branches/valkyrie_qt4port/valkyrie.pro 2010-01-08 21:43:43 UTC (rev 464)
@@ -5,12 +5,14 @@
TEMPLATE = app
SOURCES += main.cpp \
mainwindow.cpp \
- objects/vk_objects.cpp \
objects/valkyrie_object.cpp \
objects/valgrind_object.cpp \
+ objects/vk_objects.cpp \
+ options/vk_option.cpp \
options/vk_options_dialog.cpp \
- options/vk_option.cpp \
options/vk_options_page.cpp \
+ options/vk_parse_cmdline.cpp \
+ options/vk_popt.cpp \
options/valgrind_options_page.cpp \
options/valkyrie_options_page.cpp \
options/widgets/opt_base_widget.cpp \
@@ -19,18 +21,20 @@
options/widgets/opt_le_widget.cpp \
options/widgets/opt_sp_widget.cpp \
options/widgets/opt_lb_widget.cpp \
+ toolview/helgrindview.cpp \
+ toolview/memcheckview.cpp \
toolview/toolview.cpp \
- toolview/memcheckview.cpp \
- toolview/helgrindview.cpp \
- utils/vk_utils.cpp \
- utils/vk_config.cpp
+ utils/vk_config.cpp \
+ utils/vk_utils.cpp
HEADERS += mainwindow.h \
- objects/vk_objects.h \
objects/valkyrie_object.h \
objects/valgrind_object.h \
+ objects/vk_objects.h \
+ options/vk_option.h \
options/vk_options_dialog.h \
- options/vk_option.h \
options/vk_options_page.h \
+ options/vk_parse_cmdline.h \
+ options/vk_popt.h \
options/valgrind_options_page.h \
options/valkyrie_options_page.h \
options/widgets/opt_base_widget.h \
@@ -39,9 +43,9 @@
options/widgets/opt_le_widget.h \
options/widgets/opt_sp_widget.h \
options/widgets/opt_lb_widget.h \
+ toolview/helgrindview.h \
+ toolview/memcheckview.h \
toolview/toolview.h \
- toolview/memcheckview.h \
- toolview/helgrindview.h \
- utils/vk_utils.h \
- utils/vk_config.h
+ utils/vk_config.h \
+ utils/vk_utils.h
RESOURCES += icons.qrc
|